【问题标题】:What does {*} do in TCL?{*} 在 TCL 中有什么作用?
【发布时间】:2011-07-04 16:42:31
【问题描述】:

我用过一些 TCL,但这个结构让我很困惑。

当$res = "表不存在"时,下面会返回什么?

[list [list {*}$res]]

我知道[list [list $res]] 会做什么,但额外的{*} 让我感到困惑。

感谢您的帮助。

【问题讨论】:

    标签: list tcl


    【解决方案1】:

    是的,我也总是觉得施工很麻烦。它曾经被称为 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
    

    【讨论】:

    • 对此有什么想法吗?如果我有一个可以通过网络玩的地方,我本可以解决这个问题的。 stackoverflow.com/questions/5124303/…
    • 我知道你说过你想要一个基于网络的解决方案。如果找不到,请尝试 ActiveTCL activestate.com/activetcl/downloads
    • 对于您的评论“不是列表”...请记住,在 Tcl 中确实没有“是列表”或“不是列表”之类的东西,因为一切都是字符串.只有“可以作为列表处理”和“不能作为列表处理”。就像值“1”可以被视为一个int一样......它不是一个int,但你可以把它当作一个。
    【解决方案2】:

    当$res = "表不存在"时,下面会返回什么?

    [list [list {*}$res]]
    

    好吧,首先要知道[list {*}…] 是一个构造,它返回省略号中的单词列表(在您的例子中是res 变量的内容)。 碰巧在你的情况下,净效果是没有的,因为输入字符串实际上也是一个格式良好的列表。然后它成为外部list 的单个参数,因此我们得到一个单元素列表作为结果,其元素包含单词Tabledoesnotexist 按顺序排列的列表,即{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 命令特别有益;它使globauto_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 元字符,它就会崩溃……)

    【讨论】:

    • 我看到你在 TCL 董事会也很活跃。我需要将此更改反向移植到 TCL 8.4 的 C# 版本中
    • @Noah:第一个实现补丁——从 2003 年 11 月开始——位于core.tcl.tk/tcl/info/cbfb8313ba,但该功能的实现随后被多次更改(例如,使用{*} 而不是@987654344 @,并摆脱错误)。您可能需要登录该站点(以匿名身份)才能使链接正常工作。
    • @Noah:其他 Tcl 开发人员之一提醒我,已经有一个相当新的 Tcl-in-C# 版本:Eagle。 (更多链接wiki.tcl.tk/6580
    • .. 我下载了它,但很遗憾地说... % #version Eagle v1.0.4093.38850 beta NetFx20 2011.03.18(发布)用于公共语言运行时的 Tcl 8.4 兼容解释器。 % set test [list [list a {bc}]] {a {bc}} % set test [list {*}[list a {bc}]] 错误,第 1 行:大括号后的多余字符
    【解决方案3】:

    它记录在Tcl syntax manual page 上。 它在Tcl wiki 上进行了讨论。 它在TIP 293 中被引入到语言中(它的前身是TIP 157,您可以在其中了解它的工作原理)。

    本质上,{*}$res 会将字符串拆分为空格分隔的单词。所以,[list {*}$res] 的行为就像 [split $res](在这种情况下)。

    最终结果是一个包含一个元素的列表,即 $res 中的单词列表。

    【讨论】:

    • 不太一样:% llength [split {a b c {d e}}] 5 % llength [list {*}{a b c {d e}}] 4
    • @noah,是的,是的。我想 {*} 是为了扩展列表,而不是字符串。恰好OP的字符串也是一个列表。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-24
    • 2021-06-09
    • 1970-01-01
    • 1970-01-01
    • 2012-02-15
    • 1970-01-01
    相关资源
    最近更新 更多