将方括号传递到上层TCL

时间:2018-08-28 10:51:12

标签: tcl stack-trace procedure

我有一个代码,其中我正在传递要由TCl级别#0进行评估的列表。 如果我给它一个代码,该代码使用花括号以包装方括号,则效果很好,例如:

uplevel #0 { puts [ info vars CCK_* ] }

使用列表时,我无法接受:

uplevel #0 [list puts "\[" info vars CCK_* "\]" ]

我得到:

wrong # args: should be "puts ?-nonewline? ?channelId? string"
    while executing
"puts {[} info var CCK_* \]"
    ("uplevel" body line 1)
    invoked from within
"uplevel #0 [ list puts "\[" info var CCK_* "\]" ]"

我需要list命令,因为代码的其余部分需要评估变量名,这必须在上级命令执行之前(即,输入到上级)进行。例如:

if { [ getpoint $elem ] == $pointy }

[ getpoint $elem ]要在上级进行评估时,但实际上在调用proc中定义并设置了pointy,因此我不能使用大括号,它将在上级被调用之前进行评估,并且它将得到一个数字。
谢谢

3 个答案:

答案 0 :(得分:4)

您只能使用list命令来构建无单个替换命令。它专门为您引用了要做的所有事情,并且puts [info vars CCK_*]是复合命令。有几种解决方法,但是您应该仔细考虑自己的实际操作:

我引用#0只是为了突出显示。

uplevel需要什么

puts [uplevel "#0" [list info vars CCK_*]]

或者在这种情况下:

puts [uplevel "#0" {info vars CCK_*}]

将化合物包装在eval

您可以发送这样的任意内容,但我不确定为什么您会这样做:

uplevel "#0" [list eval { puts [ info vars CCK_* ] }]

发送Lambda条款

uplevel "#0" [list apply {{} {
    set vars [uplevel 1 {info vars CCK_*}]
    puts $vars
}}]

这里不是那么有用,但是当您想从当前范围中发送任意附加值时,它会变得精湛:

set value "this is a {complex string with \[some bits\] that might} make \$tcl choke"
uplevel "#0" [list apply {{value} {
    set vars [uplevel 1 {info vars CCK_*}]
    puts $value
    puts $vars
    puts $value
}} $value]

答案 1 :(得分:1)

使用list不一定能最好地组装要提交给更高级别的脚本(或命令序列)。例如,带有嵌套评估的脚本就是这种情况。

您的问题用语对我来说还不是很清楚(因此我可能对它的解释不正确),但是您可能出于您的目的考虑使用[subst][string map]

观看:

set CCK_1 ""

proc foo {someVarName} {
    uplevel "#0" [subst -nocommands {
    if {"$someVarName" in [info vars CCK_*]} {
        puts "Found $someVarName"
    }
   }]
}

foo CCK_1; # prints "Found CCK_1"
foo CCK_2

List更适合没有过多评估嵌套的命令序列;对于完整的脚本,最好使用基于[subst][string map]的脚本模板。请注意:[subst][string map]不会保护替换值,也不会以原义形式将它们放置在脚本中。

更新

这并不是说您的原始代码片段无法正常工作:

set CCK_1 ""
# a) non-robust variant
proc bar {pattern} {
    uplevel "#0" puts "\[info vars $pattern\]"
    # equiv of
    uplevel "#0" [concat puts "\[info vars $pattern\]"]
    # versus
    uplevel "#0" [list puts "\[info vars $pattern\]"]
}

bar CCK_*

set "CCK _1" ""
# b) robust variant
proc bar-robust {pattern} {
    uplevel "#0" puts "\[[list info vars $pattern]\]"
    # equiv of
    uplevel "#0" [concat puts "\[[list info vars $pattern]\]"]
}

bar-robust "CCK _*"

uplevel通过[concat]设置其参数来组合要评估的脚本。就像只提供一个[concat]'ed参数一样。您不会在这里使用list来组装整个脚本,而是要保护正在组装的脚本组件(请参见bar-robust)。这里的保护表示复杂的值在脚本汇编期间会保持其原始含义(例如,包含空格的匹配模式:CCK _*)。

答案 2 :(得分:0)

我的建议是分两步运行代码。首先,在方括号中运行代码,然后在第二次调用中使用该结果。当然,由于您只做puts,所以不需要通过uplevel来运行它:

set result [uplevel #0 [list info vars CCK_*]
puts $result

如果使用puts只是出于说明目的,那么我认为两次调用uplevel的总体想法仍然有效:将代码放在方括号中作为一个单独的步骤,然后将其与其他代码合并代码以获得最终结果。