如何使用参数列表中的参数调用过程
问题描述:
这是Tcl 8.4。如何使用参数列表中的参数调用过程
我正在试图做一个程序,可以做任何其他程序通过用户指定的共同点。
例如:
proc process_menu_item {command args {count 1}} {
set inf [expr {$count == -1 ? 1 : 0}]
set end_str [expr {$count == -1 ? "inf" : $count}]
set loop_cnt 0
while {$inf || $count > 0} {
incr loop_cnt
puts [format "------- %s -------" [bold "LOOP $loop_cnt of $end_str"]]
$command $args
}
return
}
这个过程,我希望,将只执行指定$命令$ count次。 我遇到的问题是传递参数。
假设我想打电话给这样一个过程:
proc example {{par_a {-1}} {par_b {-1}} {par_c 1}} {
puts "All params: $par_a $par_b $par_c"
}
如何我应该叫process_menu_item
?它甚至有可能吗?我尝试了一个字符串,一个列表,但最终par_a
得到所有参数的大列表。
谢谢。
答
(首先,在args
参数的程序只有当它是最后的时候才是神奇的,把它放在它后面,它就变成了一个普通的变量,当然,这可能就是你在这里所需要的!)
召唤出process_menu_item
,你会想改变:
$command $args
这个(TCL 8.4或更早):
eval $command $args
好吧,如果你是偏执你其实写这:
eval [list $command] [lrange $args 0 end]
或者你使用的Tcl 8.5(或更高版本):
$command {*}$args
然后,你可能会建立呼叫到process_menu_item
这样的:
process_menu_item frobnicate [list foo bar]
还有一些其他的方法来做到这一点,而不是使用list
(许多Tcl命令可以产生列表)或你可以使用文字:
process_menu_item frobnicate {foo bar}
什么不建议是把任何东西在字面上是指内部process_menu_item
变量(这将在与最短的基于eval
的表单一起工作)。它可以让你做出令人敬畏的东西,但它也令人难以置信的脆弱。如果你想传递循环变量,这很可能,但它需要更高级的技术(你应该问另一个问题)。
答
你总是可以构建一个包装函数:
proc wrapper {arg_list} {
example [lindex $arg_list 0] [lindex $arg_list 1] [lindex $arg_list 2]
}
TCL 8.5具有专为这样的事情的{*}
operator:
% proc test {a b c} {
puts a
puts b
puts c
}
%
% set inp [list "A" "B" "C"]
A B C
% test $inp
wrong # args: should be "test a b c"
% test {*}$inp
a
b
c
答
我现在无法给出更全面的答案,但interp alias
可能会让你想要去的地方。有一个例子at rosettacode.org。如果不适合,也许探索command traces - 那些为每个命令启动的,你可以根据命令名进行选择。
因此,必须为每个可以调用的过程编写包装器? – ilya1725 2012-04-28 00:21:37