明显的不一致 read/write 变量
apparent inconsistency read/write variable
我正在学习Tcl。我只看过一点点,我看到例如创建一个变量(并初始化它)你可以做
set varname value
我熟悉这样一个事实,基本上一切都是字符串,例如上面的“value”,但是我猜“varname”得到了某种特殊处理,因为“set”内置函数,所以 varname不被解释为一个字符串,而是一个名称。
稍后我可以使用 $varname 访问该值,这对我来说很好,它用于指定 varname 不被视为字符串。
我现在正在阅读有关列表的内容,一些命令让我有点困惑
set colors {"aqua" "maroon" "cyan"}
puts "list length is [llength $colors]"
lappend colors "purple"
很明显,“lappend”是另一个类似 set 的函数,它可以将第一个参数解释为名称而不是字符串,但为什么他们不使它的 llength 相同(不需要 $) ?
我认为这只是一个约定,一般来说,当您“读取”变量时需要 $ 而“写入”则不需要。
名称是字符串。 或者更确切地说,字符串是名称,因为它被用作名称。 $
在 Tcl 中的意思是“立即读取这个变量”, 不像在其他一些语言中它真正的意思是“这是一个变量名”。
用于从变量读取的 $blah
语法是一种方便的语法,大约代表执行 [set blah]
(只有一个参数)。对于简单的名称,它们变成了相同的字节码,但是 $…
形式并不能像另一个形式那样处理所有奇怪的边缘情况(通常使用生成的名称)。如果命令(例如 set
、lappend
、unset
或 incr
)使用变量名,那是因为它要写入该变量,通常是记录为 varName (当然是变量名)或类似的东西。只读取值的东西(例如 llength
或 lindex
)将直接获取值而不是变量的名称,调用者可以使用他们想要的任何方式提供值,也许 $blah
或 [call something]
.
特别是,如果您有:
proc ListRangeBy {from to {by 1}} {
set result {}
for {set x $from} {$x <= $to} {incr x $by} {
lappend result $x
}
return $result
}
那么你可以这样做:
llength [ListRangeBy 3 77 8]
和
set listVar [ListRangeBy 3 77 8]
llength $listVar
并从 llength
中得到完全相同的值。 llength
不需要知道任何关于正在发生的事情的特殊信息。
换个角度看问题:哪些 Tcl 命令适用于列表 literals?
对列表字面量的元素进行计数是有效的:
llength {my dog has fleas}
但是将新元素附加到文字上没有意义
lappend {my dog has fleas} and ticks
(这实际上是有效的 Tcl,但它设置了奇数变量 ${my dog has fleas}
)
这样更明智:
set mydog {my dog has fleas}
lappend mydog and ticks
我正在学习Tcl。我只看过一点点,我看到例如创建一个变量(并初始化它)你可以做
set varname value
我熟悉这样一个事实,基本上一切都是字符串,例如上面的“value”,但是我猜“varname”得到了某种特殊处理,因为“set”内置函数,所以 varname不被解释为一个字符串,而是一个名称。 稍后我可以使用 $varname 访问该值,这对我来说很好,它用于指定 varname 不被视为字符串。 我现在正在阅读有关列表的内容,一些命令让我有点困惑
set colors {"aqua" "maroon" "cyan"}
puts "list length is [llength $colors]"
lappend colors "purple"
很明显,“lappend”是另一个类似 set 的函数,它可以将第一个参数解释为名称而不是字符串,但为什么他们不使它的 llength 相同(不需要 $) ?
我认为这只是一个约定,一般来说,当您“读取”变量时需要 $ 而“写入”则不需要。
名称是字符串。 或者更确切地说,字符串是名称,因为它被用作名称。 $
在 Tcl 中的意思是“立即读取这个变量”, 不像在其他一些语言中它真正的意思是“这是一个变量名”。
用于从变量读取的 $blah
语法是一种方便的语法,大约代表执行 [set blah]
(只有一个参数)。对于简单的名称,它们变成了相同的字节码,但是 $…
形式并不能像另一个形式那样处理所有奇怪的边缘情况(通常使用生成的名称)。如果命令(例如 set
、lappend
、unset
或 incr
)使用变量名,那是因为它要写入该变量,通常是记录为 varName (当然是变量名)或类似的东西。只读取值的东西(例如 llength
或 lindex
)将直接获取值而不是变量的名称,调用者可以使用他们想要的任何方式提供值,也许 $blah
或 [call something]
.
特别是,如果您有:
proc ListRangeBy {from to {by 1}} {
set result {}
for {set x $from} {$x <= $to} {incr x $by} {
lappend result $x
}
return $result
}
那么你可以这样做:
llength [ListRangeBy 3 77 8]
和
set listVar [ListRangeBy 3 77 8]
llength $listVar
并从 llength
中得到完全相同的值。 llength
不需要知道任何关于正在发生的事情的特殊信息。
换个角度看问题:哪些 Tcl 命令适用于列表 literals?
对列表字面量的元素进行计数是有效的:
llength {my dog has fleas}
但是将新元素附加到文字上没有意义
lappend {my dog has fleas} and ticks
(这实际上是有效的 Tcl,但它设置了奇数变量 ${my dog has fleas}
)
这样更明智:
set mydog {my dog has fleas}
lappend mydog and ticks