为什么在调用“set”时Tcl在变量名之前不使用美元符号?

时间:2011-09-04 12:48:02

标签: syntax tcl

我将在这里使用Perl作为比较:

$foo = 5;
print $foo;

将变量$foo设置为5,然后打印变量的内容(注意$foo始终作为$foo访问)。

在Tcl:

set foo 5
puts $foo

与Perl对应物做同样的事情。

为什么Tcl没有用“$”设置变量,但需要“$”才能访问变量? 为什么程序也是如此(例如proc bar {spam eggs} {...})? 对我来说,Tcl代码看起来像这样(在伪代码中):

"foo" = 5 # Setting a string?
puts $foo # "$foo" is not defined.

(我的评论只反映了似乎正在发生的事情,而不是正在发生的事情)。

我想补充的另一点是清晰度:

set foo foo

是的,我总是可以set foo "foo",但set $foo foo更不一致吗?

据我所知,“foo”可以是变量或字符串,具体取决于具体情况,如我上一个例子(set foo foo = set var string)所示,但我没有得到这种语法(也许是因为我习惯了Python ......)

4 个答案:

答案 0 :(得分:13)

我认为原始Tcl只有set命令,因此获取变量“foo”内容的唯一方法是调用set foo。但随着Tcl进入通用脚本语言领域(回想一下,Tcl被设想为一种可嵌入的语言,你使用薄层Tcl而不是用C语言编写的编译组件,因此预计不会使用大量变量),认为$ varname语法糖是有用的,所以它被添加了。

换句话说,Tcl不像Perl那样使用“$”,其中“$”表示“将后面的任何内容解释为标量”,Tcl中的“$”也不表示变量。相反,它只是一个语法糖,“给我一个变量的值,其名称由紧接着的单词给出。”

答案 1 :(得分:12)

好吧,我决定评论原始问题的最后几点,但评论超出了限制,因此即使它没有解决指出的问题,我也会将其作为答案发布。我希望它会澄清一些似乎在问题中隐含的事情。

关于set foo foo的一致性的说明:你以某种错误的方式接近Tcl。 Tcl与Perl或Python完全不同,因为它几乎没有语法(实际上,就像LISP一样)。 “set foo foo”不是设置变量的语法,因为它可能是另一种语言,它是一个名为“set”的命令当前的调用,并传递两个参数 - “ foo“和”foo“;它是在“set”命令名下注册的任何内容,决定变量的名称是什么以及将其设置为什么值。同样,循环命令不是语法,而是命令。真的,值得停下来思考

for {set i 0} {$i < 10} {incr i} {
  puts $i
}

不仅仅是一个异想天开的语言设计者的想法,而是使用大括号,或者像C中的“普通”括号。相反,这里Tcl解析器解析出五个单词,将第一个单词作为命令的名称,看起来它,并将其余的词传递给它;它是for的实现,它解释那些{set i 0}{$i < 0}等并适当地执行它们。语法仅用于指定如何从输入的字符流中解析出单词。而且由于所有内容都是使用命令实现的,因此您的命令与内置命令的行为没有区别;这允许您创建与forswitch一样强大的自定义命令(类似于LISP中的宏)。在另一种语言中,这将等于以任意方式扩展sytnax的能力。

当这个想法“点击”时,Tcl将不再显得奇怪。 而且这个属性使得Tcl易于扩展(并且可嵌入):因为你从C端提供的命令与所有内置命令完全相同。

答案 2 :(得分:3)

$foo视为变量foo,即上次设置的文本。现在,如果foo目前的值为x,则set $foo y表示set x y,这显然不是什么意思。它实际上比其他语言更加一致,其中foo有时表示变量foo的值,有时表示变量foo本身。

答案 3 :(得分:2)

真正的答案,如果有的话,只能由原始语言设计师(John Ousterhout)给出。所以其余部分对投机或(受过教育的)猜测持开放态度。 TCL有一些历史可供here,但快速阅读后没有直接答案。

  

为什么Tcl不使用&#34; $&#34;设置变量,但需要&#34; $&#34;访问一个   变量?

我的看法是,它与(UNIX)shell语言更紧密地对齐。 TCL是在伯克利构思的,可以说是一个强大的UNIX(或者就此而言就是BSD)环境。

在声明或分配变量时,UNIX shell也不会使用$符号(或相应shell的等效符号),但在引用变量时需要它:

# bourn shell like shells (sh, bash, ksh, ...)
foo=foo
echo "The value of the variable foo is $foo."

即使是不圣洁的Windows CMD.EXE处理器也使用了类似的方法(虽然我猜 不是TCL设计师的想法; - )

REM DOS COMMAND.COM / Windows CMD.EXE
set foo=foo
echo The value of the variable is %foo%.

此外,&#34;字符串值&#34; (虽然shell是众所周知的弱类型)如果字符串值中现在有空格,通常不需要引号。

  

是的,我总是可以设置foo&#34; foo&#34;,但是不能设置$ foo foo更多   一致?

嗯,对于TCL设计师/创作者来说并非如此; - )

编辑我差点忘了:您实际上可以在TCL中执行以下操作:

set foo bar
set $foo something
puts $bar

这实际上会输出&#34;某些东西&#34;。第二行实际上设置字符串&#34;&#34;到变量&#34; foo&#34;的值,从而设置一个名为&#34; bar&#34;的变量。并为其分配价值&#34;&#34;。