Syntax 为什么';t Tcl在调用“时,在变量名前使用美元符号”;设置“;?

Syntax 为什么';t Tcl在调用“时,在变量名前使用美元符号”;设置“;?,syntax,tcl,Syntax,Tcl,我将在这里使用Perl作为比较: $foo = 5; print $foo; 将变量$foo设置为5,然后打印变量的内容(请注意,$foo始终作为$foo访问) 在Tcl中: set foo 5 puts $foo 执行与Perl对应项相同的操作 为什么Tcl不使用“$”设置变量,但需要一个“$”来访问变量? 为什么程序也是如此(例如,proc bar{spam eggs}{…})? 在我看来,Tcl代码如下(在伪代码中): (我的评论只反映了似乎正在发生的事情,而不是正在发生的事情) 我想

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

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

在Tcl中:

set foo 5
puts $foo
执行与Perl对应项相同的操作

为什么Tcl不使用“$”设置变量,但需要一个“$”来访问变量? 为什么程序也是如此(例如,
proc bar{spam eggs}{…}
)? 在我看来,Tcl代码如下(在伪代码中):

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

我想补充的另一点是这一点的明确性:

set foo foo
是的,我总是可以做
设置foo“foo”
,但是
设置$foo foo
不是更一致吗


据我所知,“foo”可以是变量或字符串,这取决于具体情况,正如我在上一个示例中所看到的(
setfoo-foo
=
setvar-string
),但我不明白这种语法(可能是因为我习惯了Python…

真正的答案,如果有的话,只能由最初的语言设计师给出(John Ousterhout)我想是吧。因此,其余的都是猜测或(受过教育的)猜测。TCL有一些历史,但快速阅读后没有直接的答案

为什么Tcl不使用“$”设置变量,而需要一个“$”来访问 变量

我的看法是,通过这种方式,它更接近于(UNIX)shell语言。TCL是在伯克利(Berkeley)构思的,可以说是一个强大的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设计者的想法;-)

此外,如果字符串值中现在有空格,则“字符串值”(尽管shell以弱类型著称)通常不需要引号

是的,我总是可以做set foo“foo”,但是set$foo foo不是更多吗 一致的

嗯,这不是为TCL的设计师/创造者设计的;-)

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

set foo bar
set $foo something
puts $bar

这实际上会输出“某物”。第二行实际上将字符串“something”设置为变量“foo”的值,从而设置一个名为“bar”的变量并将其赋值为“something”。将
$foo
视为变量
foo
的值,即上次设置的文本。现在,如果
foo
当前具有值
x
set$fooy
表示
set xy
,这显然不是它的意思。实际上,它比其他语言更加一致,其中
foo
有时表示变量
foo
的值,有时表示变量
foo
本身。

我认为最初的Tcl只有
set
命令,因此获取变量“foo”内容的唯一方法正在调用
set foo
。但随着Tcl进入通用脚本语言领域(回想一下,Tcl被设想为一种可嵌入语言,在C语言编写的编译组件上使用薄层Tcl,因此不需要使用大量变量),人们认为$varname语法糖是有用的,因此添加了它


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

好吧,我决定对原始问题的最后一部分进行评论,但评论超出了限制,因此我将把它作为一个答案发布,即使它没有解决指定的问题。我希望它能澄清一些问题中隐含的东西

关于
setfoo-foo
一致性的一点注意:您以一种有点错误的方式接近Tcl。Tcl与Perl或Python完全不同,因为它几乎没有语法(实际上,像LISPs)。“set-foo-foo”不是一种用于设置变量的语法,因为它可以是另一种语言,它是对当前名为“set”的命令的调用,并将两个参数传递给它--“foo”和“foo”;在“set”命令名下注册的内容决定变量的名称和设置值。同样,循环命令不是语法,而是命令。真的,值得停下来想想

for {set i 0} {$i < 10} {incr i} {
  puts $i
}
对于{set i 0}{$i<10}{incr i}{
投入$i
}
这不仅仅是一个异想天开的语言设计师的想法,即使用大括号代替C中的“普通”括号。相反,在这里,Tcl解析器解析出五个单词,将第一个单词作为命令名,查找它,并将其余单词传递给它;它是
for
的实现,它解释那些
{set i 0}
{$i<0}
等,并适当地执行它们。语法仅用于指定如何从输入字符流中解析出这些单词。因为所有的东西都是使用命令实现的,所以您的命令的行为与内置命令没有什么不同;这允许您为或开关创建功能强大的自定义命令(类似于LISPs中的宏)。在另一种语言中,这相当于以任意方式扩展sytnax的能力

当这个想法“点击”时,Tcl将不再显得怪异。 正是这个属性使得Tcl很容易扩展(和嵌入):因为您从C端提供的命令与所有内置命令的行为完全相同。

这是一个有趣的hac
set foo bar
set $foo something
puts $bar
for {set i 0} {$i < 10} {incr i} {
  puts $i
}