本文介绍了两级飞溅TCL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我在TCL中有一个过程或命令,且参数数目可变,则可以使用散列"运算符,例如,如果列表的元素作为输入,则可以使用:

If I have a procedure or a command in TCL, with variable number of arguments, one can use, if a list's elements are as an input, the "splatter" operator, for example:

set a [list "ko" ]
set m [ list "ok" "bang" ]
lappend a {*}$m

但是,如果我想两次飞溅"怎么办?即,将2个级别展平?依次使用两次,将无法正常工作:

But, what if I want to "twice splatter"? I.e., flatten 2 levels? Using it twice, in sequence, does not work:

set a [list "ko" ]
set m [ list [ list "ok" ] [ list "bang" ] ]
lappend a {*}{*}$m

多余的字符会出错.

推荐答案

您已经注意到,{*}(故意)没有深入两步.

You've noticed that {*} (deliberately) doesn't go two steps deep.

您的特定示例并不能很好地说明问题,所以我建议这样做:

Your particular example isn't very indicative of the problem, so I suggest this:

set a [list "ko" ]
set m [list [list "a b" "c d"] [list "e f" "g h"]]
lappend a {*}$m

在这里,我们将a设置为ko {{a b} {c d}} {{e f} {g h}}.这不是您想要的.但是我们可以改为:

Here, we get a set to ko {{a b} {c d}} {{e f} {g h}}. Which isn't what you wanted. But we can instead do this:

lappend a {*}[concat {*}$m]

给出以下内容:ko {a b} {c d} {e f} {g h}.看起来不错.

Which gives this: ko {a b} {c d} {e f} {g h}. That looks right.

但是我们真的真的在这里做正确的事吗?让我们用我们的超级秘密内省者representation命令戳入内部:

But are we really doing the right thing here? Let's poke inside with our super-secret introspector, the representation command:

% tcl::unsupported::representation $m
value is a list with a refcount of 4, object pointer at 0x10085ec50, internal representation 0x103016790:0x0, string representation "{{a b} {c d}}..."
% tcl::unsupported::representation [concat {*}$m]
value is a string with a refcount of 1, object pointer at 0x10085de10, internal representation 0x1030052d0:0x10085f190, string representation "{a b} {c d} {..."

哦,哦!我们已经失去了榜单.这不是灾难,但这不是我们想要的.相反,我们应该这样做:

Uh oh! We've lost the list-ness. It's not a catastrophe, but it isn't what we wanted. We instead should really do:

foreach sublist $m {
    lappend a {*}$sublist
}

好吧,这是更多的代码,但是保留了列表式(如果您碰巧在叶子上有珍贵的类型,那将是很好的; Tcl核心没有这种珍贵的类型,但是有些扩展却有).

Well, that's more code but preserves list-ness (which would be good if you happened to have precious types on the leaves; core Tcl doesn't have such precious types, but some extensions do).

我们可以比较时间:

% time {
    set a [list "ko" ]
    set m [list [list "a b" "c d"] [list "e f" "g h"]]
    lappend a {*}[concat {*}$m]
} 10000
2.852789 microseconds per iteration
% time {
    set a [list "ko" ]
    set m [list [list "a b" "c d"] [list "e f" "g h"]]
    foreach sublist $m {
        lappend a {*}$sublist
    }
} 10000
4.022959 microseconds per iteration

哦...

% time {apply {{} {
    set a [list "ko" ]
    set m [list [list "a b" "c d"] [list "e f" "g h"]]
    lappend a {*}[concat {*}$m]
}}} 10000
2.4486125 microseconds per iteration
% time {apply {{} {
    set a [list "ko" ]
    set m [list [list "a b" "c d"] [list "e f" "g h"]]
    foreach sublist $m {
        lappend a {*}$sublist
    }
}}} 10000
1.6870501 microseconds per iteration

哈!类型正确的方法在过程(如上下文)中更好.

Hah! The type-correct one is better in a procedure(-like context).

这篇关于两级飞溅TCL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-13 19:38