花括号为什么允许变量替换?

时间:2019-08-18 16:08:03

标签: tcl tclsh

Tcl手册说花括号不允许变量替换。 但是,这仅适用于某些命令,而不适用于其他命令。

有什么区别,以及如何识别将发生替代和不发生替代的情况?

% set x 3
3
% puts {$x}
$x
% expr {$x}
3

3 个答案:

答案 0 :(得分:3)

答案 1 :(得分:3)

请参阅standard commands的列表:任何带有“ body”或“ script”自变量的命令最终都会将该主体评估为代码。无法保证详尽无遗:

  

afterapplycatchevalexprfileevent(和chan event),{{1 }},forforeachifinterp eval,一些lmap子命令,一些namespace命令,oo::*,{ {1}},procsubstswitchtry

这确实是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