2008-10-31 59 views
2

与TCL合作,我想实施类似Strategy Pattern的东西。我想通过TCL功能打印输出的“策略”,所以我可以轻松地在打印到屏幕和打印到日志文件之间切换。在TCL中做这件事的最好方法是什么?TCL是否有一些函数指针的概念?

+0

,如果你的问题是关于执行该战略格局不要问在TCL函数指针。 – JesperE 2008-10-31 13:24:31

回答

18

TCL允许您将过程的名称存储在变量中,然后使用该变量调用该过程;所以

proc A { x } { 
    puts $x 
} 

set strat A 
$strat Hello 

将调用程序A并打印出您好

1

如何使用可变函数?我不记得了TCL(它已经有一段时间...),但也许这些人会做你的需要:

  • [$ VAR参数1参数2]
  • [$ VAR]参数1参数2
  • $ var param1 param2

如果我错了,任何人都可以自由纠正我。

+0

这是你应该使用的最后一个。 – 2008-10-31 14:24:04

4

稍微扩大了什么上面列出的可能说明了策略模式更清晰的例子:

proc PrintToPDF {document} { 
<snip logic> 
} 

proc PrintToScreen {document} { 
<snip logic> 
} 

proc PrintToPrinter {document} { 
<snip logic> 
} 


set document "my cool formatted document here" 

set printMethod "printer" 


switch -- $printMethod { 
    "printer" { 
     set pMethodName "PrintToPrinter" 
    } 
    "pdf" { 
     set pMethodName "PrintToScreen" 
    } 
    "screen" { 
     set pMethodName "PrintToPDF" 
    } 
} 

$pMethodName $document 
4

除显示如何将过程分配给变量的答案,还可以将过程的名称作为参数传递给另一个过程。这里有一个简单的例子:


proc foo { a } { 
    puts "a = $a" 
} 

proc bar { b } { 
    puts "b = $b" 
} 

proc foobar { c } { 
    $c 1 
} 

foobar foo 
foobar bar 

这将打印= 1,B = 1

0

解释,为什么杰克逊的方法工作,记得在TCL,一切是一个字符串。无论你使用的是文字字符串,函数,变量还是其他任何东西,所有的都是一个字符串。您可以像“数据指针”一样传递“函数指针”:只需使用不带前导“$”的对象名称即可。

3

除了使用proc之外,您实际上可以使用代码块。这有几个变化。首先是最明显的,只是eval而已。

set strategy { 
    puts $x 
} 

set x "Hello" 
eval $strategy 
unset x 

这个工程,但有几个缺点。首先显而易见的是,这两部分代码必须混合使用一个通用的命名参数。这取代了一个命名空间头痛(procs)与另一个(本地人),这可以说实际上是更糟糕的

不太明显的是,eval故意在不编译字节码的情况下解释它的参数。这是因为假设eval将被动态生成,通常是唯一的参数来调用,并且如果字节码只能被使用一次,相对于立即解释块而言,编译为字节码将是低效的。这是比较容易解决,所以这里的成语:

set x "Hello" 
if 1 $strategy 
unset x 

if,不像eval,并编译和缓存的代码块。如果$strategy块只有一个或只有少数不同的可能值,那么这个工作就很好。

这并不能解决将局部变量传递给模块的麻烦。有很多方法,比如像substitutions一样使用tk替换命令参数%'s。你可以尝试使用uplevelupvar做一些骇人的事情。例如,你可以这样做:

set strategy { 
    puts %x 
} 

if 1 [string map [list %% % %x Hello] $strategy] 

上关的机会,传递的参数不发生很大的变化,这非常适用于字节码编译的条款。另一方面,如果参数经常变化,则应使用eval而不是if 1。无论如何,就论据而言,这并不是好得多。由于您使用了特殊的语法,所以传递的内容和不传递的内容不太可能混淆。如果您想在返回代码块之前使用变量替换,这也很有用:如在set strategy "$localvar %x"中。

幸运的是,tcl 8.5有true anonymous functions,使用apply命令。 apply命令的第一个单词是参数和主体的列表,就像proc的参数已被解除一样。其余参数立即作为参数传递给匿名命令。

set strategy [list {x} { 
    puts $x 
}] 

apply $strategy "Hello" 
+0

+1 for Tcl 8.5 information – 2009-07-25 04:59:01

1
% set val 4444 
4444 

% set pointer val 
val 

% eval puts $$pointer 
4444 

% puts [ set $pointer ] 
4444 

% set tmp [ set $pointer ] 
4444