我刚刚在tclsh中尝试了以下内容:
proc pp {$ag} { puts hi}
pp whatever
令我惊讶的是,这很好用!我曾预料到语法错误,因为proc参数是一个变量。但似乎tcl很好。
然后我进行了实验:
proc pp {$ag} { puts "hi $ag"}
pp whatever
和
proc pp {$ag} { puts "hi ${$ag}"}
pp whatever
我收到了错误can't read "ag": no such variable
。
这让我想知道,proc的论点可以变量吗?如果没有,为什么不在第一个脚本中输出错误?
答案 0 :(得分:3)
第一种情况有效,因为您从未将参数用于pp
。
当您调用proc
命令时,将调用调用文本,就像在任何其他命令调用中一样。在所有上述情况中,第三个参数(将成为pp
命令的参数列表)包含在大括号中,这意味着它不会被评估为变量,而是作为三个字符串的字符串字符:" $ ag" (即美元符号在这里只是一个常规字符)。这不是一个错误,并且确实有效,而不是你想象的那样。
获取参数$ag
的值有点棘手。这有效:
proc pp {$ag} {puts "hi [set {$ag}]"}
美元符号实际上只是一元set
命令的语法糖。有时候美元符号不会起作用,你需要回到明确的set
。
但这确实有效:
proc pp {$ag} {puts "hi ${$ag}"}
所以,在你的调用中,proc
的第三个参数实际上并不是一个变量评估,它只是一个。当然,您可以在调用proc
:
set foo {bar baz}
proc qux $foo {puts $bar ; puts $baz}
qux abc def
# => abc
# => def
Tcl解释器在这里真正看到的是:
proc qux {bar baz} {puts $bar ; puts $baz}
或者你真的很疯狂:
set foa {proc qux}
set fob {bar}
lappend fob baz
set foc {puts $bar}
set fod "puts \$baz"
{*}$foa $fob [join [list $foc $fod] { ; }]
与前一次proc
的调用相同。 (如果你不相信我,试试list {*}$foa $fob [join [list $foc $fod] { ; }]
)
这个例子看起来很奇怪,但很多时候它在程序中构造新命令实际上很有用,在这些情况下,调用中使用的文本真的很好。与任何其他命令一样,proc只是可以应用Tcl的评估规则的文本。您可以对其使用任何类型的字符串或列表操作,并连接来自各种来源的文本,甚至是用户输入(如果您可以信任它)。
文档:Tcl evaluation rules including $ and {*},join,lappend,list,proc,puts,set