Tcl 大括号引用:大括号内的所有内容都是文字吗?

Tcl brace quoting: is everything literal inside braces?

我读过,braace {} 中的所有内容都是文字(Tcl 中的反斜杠换行符除外。 所以,这是预期的:

% puts {\{}
\{

但是,我没有正确理解以下内容:

% puts { {}
 <waits for close brace>

我希望它打印 {,因为它在大括号内,应该按字面意思理解。我期望的是:一旦遇到左括号,就按字面意思理解所有内容,直到遇到第一个右括号。但这似乎并没有发生。请解开我的误会。

对于 Tcl 程序员来说,大括号总是乞讨时的噩梦。

如您所知,大括号的主要经验法则如下,

规则 1:大括号内没有替换发生

除上述规则外,我们在 Tcl.

中还有一些其他规则

大括号最重要的用途之一是defer evaluation

规则 2:延迟评估

这意味着 Tcl 解析器不会立即处理特殊字符。

相反,它们将作为参数的一部分传递给命令过程,命令过程将自行处理特殊字符。将脚本传递给 Tcl 命令时几乎总是使用大括号,如下例计算五的阶乘:

   set result 1 
   set i 5 
   while {$i > 0} { 
         set result [expr $result*$i] 
         set i [expr $i-1] 
   } 

while 循环体用大括号括起来以延迟替换。 While 将脚本传回 Tcl 以在循环的每次迭代期间进行评估,届时将执行替换。在这种情况下,延迟替换很重要,这样每次 while 计算循环体时它们都会重新完成,而不是在解析 while 命令时一劳永逸。

规则 3:大括号嵌套。 proc 命令的最后一个单词在第一行的左大括号之后开始,并包含直到右大括号的所有内容最后一行。

规则 4:Tcl 解释器移除外括号并将它们之间的所有内容(包括几对嵌套的括号)作为参数传递给 proc

proc power {base p} { 
    set result 1 
    while {$p > 0} { 
          set result [expr $result*base] 
          set p [expr $p-1] 
     } 
    return $result 
}

在上面的例子中,proc 的第三个参数包含两对嵌套大括号(最外面的大括号被 Tcl 解析器移除)。当解析 proc 命令时,甚至当 while 命令被解析为执行过程主体的一部分时,将不会执行使用 [expr $p-1] 请求的命令替换,但仅当 while 评估其第二个参数以执行循环。

规则 5:如果大括号是反斜杠,则它不计入大括号中包含的单词的匹配右大括号的结尾。解析单词时不会删除反斜杠。

如规则 4 中所述,在代码 puts {\{} 中,删除外括号后,我们只有 \{。这将传递给 puts 命令。现在,根据规则 5,在 \{ 中,当 Tcl 遇到反斜杠左大括号时,它不会尝试匹配右大括号。此外,解析时不会删除该反斜杠。这就是 \{ 在控制台中打印的原因。

puts {{} 的情况下,Tcl 解释器显然会等待右大括号,因为它是不平衡的。

注意:所有地方都会出现异常。好吧,Tcl 在大括号方面也一样。我们开始说大括号内没有替换。但是,大括号之间出现的唯一替换形式是反斜杠换行符。

Tcl中,backslash也用于续行。

if 1 {
 puts "Brace Yourself!!!"
}

你可以把上面的改写成

if 1 \
{
 puts "Brace Yourself!!!"
}

同理,使用反斜杠换行,替换将如下所示。

puts {Thanks to\
Whosebug}

代码的输出将显示在一行中。

参考:Tcl and the Tk Toolkit

大括号嵌套(除非引用)在大括号内,因为这是规则(Dodekalogue 中的 [6])。这条规则的原因是大括号单词的内容通常是一个结构化的表达式,带有几个左括号和右括号,甚至很可能是几个 levels 的左括号和右括号。当您没有使用大括号来构建表达式时,让解析器抱怨不平衡大括号的好处超过了必须引用大括号的麻烦。

Tcl syntax