所以我有以下情况:
$ ls -l
-r--r----- 1.tcl
-rw-rw---- 2.tcl
$ cat 1.tcl
proc foo {args} {
puts "$bar"
}
我需要1.tcl
打印"can't read \"bar\""
以外的内容。在一个好的编程语言中,显而易见的解决方案是
$ cat > 2.tcl
set -global bar "hello, world"
foo
TCL的合理解决方法是什么?不幸的是,真正的foo
是一个很长的函数,我无法在运行时将sed
复制到临时文件中。
答案 0 :(得分:1)
您可以为您的具体示例执行
$ cat 2.tcl
source 1.tcl
set bar "Hello, bar!"
# add a "global bar" command to the foo procedure
proc foo [info args foo] "global bar; [info body foo]"
foo
$ tclsh 2.tcl
Hello, bar!
显然,这并不能很好地扩展。
答案 1 :(得分:1)
如果变量只是未定义,最简单的方法是使用定义修补过程:
proc foo [info args foo] "set bar \"hello, world\" ; [info body foo]"
您还可以使用读取跟踪和帮助程序命令来完成此操作。这消除了我上面提到的问题,其中本地分配破坏了你想要注入的值。
原始过程,添加了一个命令,将局部变量设置为稍后打印的值。
proc foo args {
set bar foobar
puts "$bar"
}
% foo
foobar
创建一个全局变量(如果名称相同或无关,则无关紧要。)
set bar "hello, world"
创建一个帮助程序命令,该命令获取局部变量的名称,链接到该变量,并为其分配全局变量的值。由于我们已经知道了名称,我们可以在程序中对其进行硬编码,但这更灵活。
proc readbar {name args} {
upvar 1 $name var
global bar
set var $bar
}
将跟踪添加到foo
过程的主体。只要读取局部变量bar
,就会触发跟踪,即某些东西试图检索其值。触发跟踪时,将调用命令readbar
:它使用全局设置值覆盖变量的当前值。
proc foo [info args foo] "trace add variable bar read readbar; [info body foo]"
% foo
hello, world
如果不希望使用helper命令污染命名空间,可以使用匿名函数:
proc foo [info args foo] [format {trace add variable bar read {apply {{name args} {
upvar 1 $name var
global bar
set var $bar
}}} ; %s} [info body foo]]
文档: apply, format, global, info, proc, puts, set, trace, upvar, Syntax of Tcl regular expressions
答案 2 :(得分:0)
source 1.tcl
try {
foo
} on error {err res} {
set einfo [dict get $res -errorinfo]
if { [regexp {no such variable} $einfo] } {
puts "hello, world"
return -code 0
} else {
puts $einfo
return -code [dict get $res -code]
}
}
答案 3 :(得分:0)
默认情况下,Tcl的过程不会将变量解析为除局部变量之外的任何变量。您必须明确要求他们引用其他内容(例如,使用global
,variable
或upvar
)。这意味着总是可以一目了然地看到非本地事情是否正在发生,并且脚本将不起作用。
可以使用变量解析器覆盖此行为,但Tcl并未真正在其脚本接口中公开该API。一些扩展做得更多。例如,可能使用[incr Tcl](即itcl),因为它对其对象中的变量执行此类操作。我不记得Expect是否也这样做了,或者是否使用特殊代码来处理变量。
当然,你可能会偷偷摸摸地改写proc
的行为。
rename proc real_proc
real_proc proc {name arguments body} {
uplevel 1 [list real_proc $name $arguments "global bar;$body"]
}
虽然这很讨厌。