Tcl手册说花括号不允许变量替换。 但是,这仅适用于某些命令,而不适用于其他命令。
有什么区别,以及如何识别将发生替代和不发生替代的情况?
% set x 3
3
% puts {$x}
$x
% expr {$x}
3
答案 0 :(得分:3)
这是关于双重替代。 检查以下链接: https://wiki.tcl-lang.org/page/double+substitution https://wiki.tcl-lang.org/page/Brace+your+expr-essions
答案 1 :(得分:3)
请参阅standard commands的列表:任何带有“ body”或“ script”自变量的命令最终都会将该主体评估为代码。无法保证详尽无遗:
after
,apply
,catch
,eval
,expr
,fileevent
(和chan event
),{{1 }},for
,foreach
,if
,interp eval
,一些lmap
子命令,一些namespace
命令,oo::*
,{ {1}},proc
,subst
,switch
,try
这确实是Tcl的最大优势之一。它使您能够轻松编写自己的控制结构。例如,Tcl不提供do-while循环,但是您可以这样做:
uplevel
这样
while
答案 2 :(得分:2)
某些命令被明确地描述为将一个或多个参数视为脚本或表达式;当脚本或表达式的求值发生时(取决于命令,可能立即执行,也可能稍后执行),将在作为脚本或表达式的字符串中描述替换。 (subst
命令是一种特殊情况,只能应用选定的替换子集。)
您怎么知道哪个? 这取决于命令。从字面上看。去阅读文档。例如,在the documentation for catch
中,我们看到:
简介
捕获 脚本? resultVarName ? ? optionsVarName ?
说明
catch 命令可用于防止错误中止命令解释。 catch 命令以递归方式调用Tcl解释器以执行 script ,并且无论执行 script 。 […]
在这种情况下,我们看到始终通过调用Tcl解释器将第一个参数作为Tcl脚本(立即)进行评估(或者在大多数情况下实际上是字节码编译,但这是实现细节)。
类似地,在the documentation for proc
中,我们看到:
简介
过程 名称参数主体
说明
proc 命令创建一个名为 name 的新Tcl过程,用该名称替换任何现有的命令或过程。每当调用新命令时, body 的内容将由Tcl解释器执行。 […]
在这种情况下,将 body 作为脚本进行评估(“通过Tcl解释器”是一种语言形式,表示该语言),但是稍后,当该过程被调用时。 (catch
对此一无所知;这意味着它会立即采取行动。)
第三种情况是the documentation for while
:
简介
同时同时测试正文
说明
while 命令将 test 评估为表达式(与 expr 评估其参数的方式相同)。表达式的值必须为正确的布尔值;如果它是一个真值,则将 body 传递给Tcl解释器来执行。 […]
由此可见, test 参数是一个表达式(使用表达式规则),而 body 是一个脚本。
如果您要创建一个无替换的单命令脚本,可以在其中使用所有值的任意值(非常适合设置回调),请使用list
命令,被定义为产生规范形式的列表,(通过设计)这种形式恰好是没有替换惊喜的单个命令可以采用的形式:
set xyz "123 456"
set callback [list puts $xyz]
set xyz {[crash bang wallop]}
puts "READY..."
eval $callback