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

Tcl 为什么大括号允许变量替换?,tcl,tclsh,Tcl,Tclsh,Tcl手册说大括号不允许变量替换。 但是,这仅适用于某些命令,而不适用于其他命令 区别是什么?如何确定替代将发生的情况和不发生的情况 % set x 3 3 % puts {$x} $x % expr {$x} 3 引用列表:任何接受“body”或“script”参数的命令最终都会将该body作为代码进行计算。没有关于用尽的保证: 之后,应用,捕获,评估,导出,文件事件(和chan事件),为,如果,内部评估,lmap,一些命名空间子命令,一些oo:命令,程序,subst,开关,try,uple

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

区别是什么?如何确定替代将发生的情况和不发生的情况

% set x 3
3
% puts {$x}
$x
% expr {$x}
3
引用列表:任何接受“body”或“script”参数的命令最终都会将该body作为代码进行计算。没有关于用尽的保证:

之后
应用
捕获
评估
导出
文件事件
(和
chan事件
),
如果
内部评估
lmap
,一些
命名空间
子命令,一些
oo:
命令,程序,
subst
开关
try
uplevel
while

这确实是Tcl最大的优势之一。它使您能够轻松编写自己的控制结构。例如,Tcl不提供do while循环,但您可以这样做:

proc do {body while condition} {
    if {$while ni {while until}} {
        error "some message about usage..."
    }
    while true {
        uplevel 1 $body
        set status [uplevel 1 [list expr $condition]]
        if {$while eq "while" && !$status} then break
        if {$while eq "until" &&  $status} then break
    }
}
所以

% set i 0; while {[incr i] < 3} {puts "$i"}
1
2
% set i 0; do {puts "$i"} while {[incr i] < 3}
0
1
2
% set i 0; do {puts "$i"} until {[incr i] == 3}
0
1
2
%set i 0;而{[incr i]<3}{put“$i”}
1.
2.
%设i0;当{[incr i]<3}
0
1.
2.
%设i0;在{[incr i]==3}之前{放置“$i”}
0
1.
2.
一些命令被明确描述为将一个或多个参数视为脚本或表达式;当脚本或表达式的计算发生时(可能是立即的,也可能是稍后的,具体取决于命令),将执行脚本或表达式字符串中描述的替换。(
substict
命令是一种特殊情况,只能应用选定的替换子集。)

你怎么知道哪个是哪个这取决于命令。字面意思。去阅读文档。例如,在中,我们看到:

提要 catchscript?resultVarName?选项varname

描述 catch命令可用于防止错误中止命令解释。catch命令递归调用Tcl解释器来执行脚本,并且始终返回而不引发错误,而不管执行脚本时可能发生的任何错误。[……]

在本例中,我们看到第一个参数总是(立即)通过调用Tcl解释器作为Tcl脚本进行计算(或者更确切地说,在大多数情况下它实际上是编译的字节码,但这是一个实现细节)

同样地,我们看到:

提要 proc名称参数正文

描述 proc命令创建一个名为name的新Tcl过程,用该名称替换可能存在的任何现有命令或过程。每当调用新命令时,body的内容都将由Tcl解释器执行。[……]

在本例中,主体将作为脚本进行求值(“由Tcl解释器”是一种表示这一点的语言形式),但稍后,当调用过程时。(
catch
对此只字未提;言下之意,它会立即采取行动。)

第三种情况是:

提要 测试主体

描述 while命令将test作为表达式进行计算(与expr计算其参数的方式相同)。表达式的值必须是正确的布尔值;如果它是真值,则通过将其传递给Tcl解释器来执行body。[……]

由此,我们可以看到test参数是一个表达式(使用表达式规则),body是一个脚本


如果您想创建一个无替换的单命令脚本,在该脚本中,您可以对所有内容使用任意值(这非常适合设置回调),请使用
list
命令,该命令被定义为以规范形式生成列表,这种情况会发生(通过设计)这正是没有替代惊喜的单个命令可以采用的形式:

set xyz "123 456"
set callback [list puts $xyz]
set xyz {[crash bang wallop]}
puts "READY..."
eval $callback

这是关于双重替代。查看这些链接:谢谢。我知道像expr这样的一些命令会自己进行额外的替换。问题在于如何区分哪个命令执行,哪个命令不执行。我找不到执行第二轮替换的命令的完整列表。这种不完整性对于初学编程的人来说是相当令人困惑的,并且可能使代码暴露在注入攻击之下。我认为在一开始就足够了)你可以阅读。本页详细讨论了大括号在Tcl中的含义。