如何在tcl中将变量参数从一个函数传递给另一个函数

vai*_*war 4 tcl variadic-functions

我想将在一个函数中获得的变量参数传递给其他函数,但我无法这样做.函数获得偶数个变量参数,然后必须在数组中转换.以下是示例.

过程abc1获取两个参数(k k)而不是表单abc1过程,这些必须传递给proc abc,其中list要进行数组转换.列表到数组转换在proc1中工作,abc1但不在第二个proc中工作abc

获得的错误如下

proc abc {args} {
    puts "$args"
    array set arg $args
}

proc abc1 {args} {
    puts "$args"
    array set arg $args
    set l2 [array get arg]
    abc $l2
}

abc1 k k
abc k k
Run Code Online (Sandbox Code Playgroud)

输出:

k k
{k k}
list must have an even number of elements
    while executing
"array set arg $l1"
    (procedure "abc" line 8)
    invoked from within
"abc $l2"
    (procedure "abc1" line 5)
    invoked from within
"abc1 k k"
    (file "vfunction.tcl" line 18)
Run Code Online (Sandbox Code Playgroud)

Don*_*ows 13

最佳解决方案:扩展替代

正确的方法是确保外部过程(以堆栈术语)正确地调用内部过程; 如果预期有多个参数,那就是应该提供的参数.随着Tcl 8.5的出现,使用一种称为扩展替换的语言语法非常简单:

proc abc1 {args} {
    puts "$args"
    array set arg $args
    set l2 [array get arg]
    abc {*}$l2
    # Or combine the two lines above into: abc {*}[array get arg]
}
Run Code Online (Sandbox Code Playgroud)

所有这些{*}都是说应该分解其余部分(使用列表语法规则)并用作多个参数而不是Tcl的默认"一个视觉词形成一个单词"规则.这是理想的.

旧解决方案:Eval命令

如果由于某种原因(即Tcl 8.4或之前)仍在使用旧版本的Tcl,那么您使用eval命令而不是上述语法:

eval abc $l2
Run Code Online (Sandbox Code Playgroud)

对于上述方法,有一些更有效的方法eval,您可能会在旧代码中看到这些方法; 例如:

eval [linsert $l2 0 abc]
eval [list abc] [lrange $l2 0 end]
# ... etc ...
Run Code Online (Sandbox Code Playgroud)

但实际上它们都变得过时了abc {*}$l2,更短,更简单,写得更快.(它仅在8.4或之前不可用,并且有太多部署尚未升级.)如果可以,请使用扩展语法.事实上,8.5及以后的惯用Tcl代码几乎不需要eval; 事实证明这一点的真实程度对语言的维护者来说甚至相当令人惊讶.