【发布时间】:2011-07-04 16:42:31
【问题描述】:
我用过一些 TCL,但这个结构让我很困惑。
当$res = "表不存在"时,下面会返回什么?
[list [list {*}$res]]
我知道[list [list $res]] 会做什么,但额外的{*} 让我感到困惑。
感谢您的帮助。
【问题讨论】:
我用过一些 TCL,但这个结构让我很困惑。
当$res = "表不存在"时,下面会返回什么?
[list [list {*}$res]]
我知道[list [list $res]] 会做什么,但额外的{*} 让我感到困惑。
感谢您的帮助。
【问题讨论】:
是的,我也总是觉得施工很麻烦。它曾经被称为 expand,然后他们巧妙地将其重命名为 {*}(非常令人难忘!)。无论如何,我已经看到它用于扩展列表以使列表内容可用。
请参阅此示例以了解其工作原理:
% set c [list a b]
a b
% set d [list e f]
e f
% set x [list $c {*}$d]
{a b} e f
% set y [lindex $x 2]
f
% set y [lindex $x 1]
e
% set y [lindex $x 0]
a b
【讨论】:
当$res = "表不存在"时,下面会返回什么?
[list [list {*}$res]]
好吧,首先要知道[list {*}…] 是一个构造,它返回省略号中的单词列表(在您的例子中是res 变量的内容)。 碰巧在你的情况下,净效果是没有的,因为输入字符串实际上也是一个格式良好的列表。然后它成为外部list 的单个参数,因此我们得到一个单元素列表作为结果,其元素包含单词Table、does、not 和exist 按顺序排列的列表,即{Table does not exist}。
扩展单词形式的列表对于做列表的连接很有用; concat 命令做了类似的事情(但不完全相同;concat 命令涉及一些历史上的怪事)。因此,您可以像这样连接两个列表:
set concatenation [list {*}$list1 {*}$list2]
还要注意扩展(在 Tcl 8.5 中引入)是真正的语法,这在 Tcl 中是非常不寻常的事情。 {*} 改变了以下替换的性质,使其产生多个单词而不是一个单词。虽然没有它是可能的,但实际上很难做到正确。例如,如果没有它,上面将是:
set concatenation [eval [linsert $list1 0 list] [lrange $list2 0 end]]
扩展的引入大大减少了大多数 Tcl 代码中对eval 的调用次数(这是一个好处,因为它很难正确编写;很多程序员都被这种困难所困扰)。这在实践中证明对exec 命令特别有益;它使glob 和auto_execok 的工作变得更加容易:
exec {*}[auto_execok $someCmd] $arg1 {*}[glob *.foo]
# Instead of:
#eval [linsert [auto_execok $someCmd] 0 exec] [linsert [glob *.foo] 0 $arg1]
# Or this _wrong_ version:
#eval exec [auto_execok $someCmd] $arg1 [glob *.foo]
呃。尽管我知道自己在做什么,但最后一个以非扩展形式写出来有点令人费解。 (错误的版本是错误的,因为如果$arg1 包含 Tcl 元字符,它就会崩溃……)
【讨论】:
{*} 而不是@987654344 @,并摆脱错误)。您可能需要登录该站点(以匿名身份)才能使链接正常工作。
它记录在Tcl syntax manual page 上。 它在Tcl wiki 上进行了讨论。 它在TIP 293 中被引入到语言中(它的前身是TIP 157,您可以在其中了解它的工作原理)。
本质上,{*}$res 会将字符串拆分为空格分隔的单词。所以,[list {*}$res] 的行为就像 [split $res](在这种情况下)。
最终结果是一个包含一个元素的列表,即 $res 中的单词列表。
【讨论】: