将方括号传递给上层 TCL

pass square brace to uplevel TCL

我有一个代码,我在其中传递了一个要由 TCl uplevel #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 命令,因为其余部分代码需要评估变量名,这必须在 uplevel 接受命令之前发生(即输入到 uplevel)。例如:

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

[ getpoint $elem ]要在uplevel中求值时,但pointy实际上是在调用proc中定义和设置的,因此我不能为它使用花括号,在调用uplevel之前会有求值,并且它只会得到一个数字。
谢谢,

组装脚本(或命令序列)以提交给上层等不一定使用 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

列表更适合没有过多嵌套的命令序列;对于完整的脚本,最好使用基于 [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 assembles 要通过 [concat]ing 参数评估的脚本。就像提供一个 [concat]'ed 的论点一样。您不会在此处使用 list 来 assemble 整个脚本,而是保护程序集下的脚本组件(请参阅 bar-robust)。此处的保护意味着复杂值在脚本组装期间保持其原始含义(例如,包含空格的匹配模式:CCK _*)。

我的建议是 运行 分两步编写代码。首先,运行 方括号中的代码,然后在第二次调用中使用该代码的结果。当然,因为你只是在做一个 puts,所以没有必要 运行 通过 uplevel:

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

如果使用 puts 是为了说明目的,那么我认为调用 uplevel 两次的一般想法仍然有效:运行 方括号中的代码作为一个独特的步骤,然后将其与您的其他代码结合以获得最终结果。

您只能使用 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
}}]

它在这里不是很有用,但是当你想从当前范围发送任意附加值时,它会变成 superb:

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]