如何使Tcl循环变量存在于循环内,类似于Perl foreach my

时间:2016-06-08 08:28:01

标签: variables for-loop scope closures tcl

参见Tcl shell代码&结果如下:

% foreach a { 1 2 3 4 5 } { puts $a }
1
2
3
4
5
% puts $a
5

看起来变量a留在内存中...在Perl中,例如可以使用:

foreach my $a

并且在循环期间存在$ a。在Ruby中,可以使用闭包:

[1,2,3,4,5].each{|a| puts a.to_s() }

为了达到同样的目的 在Tcl中是否有一种优雅的方式?
谢谢

2 个答案:

答案 0 :(得分:1)

您可以在闭包内迭代:

// Note that you have to build a custom type for your list items to keep high performance,
// or write this inline instead of as a function, to avoid the perf hit of IList<dynamic>
bool IsMySpecificListTypeSorted(List<MyCustomListItemType> theList) {
    int previousOrdinal = -1;

    // Not using foreach because it is "8x slower" in tests
    // and you're micro-optimizing in this scenario
    for(int index = 0; index < theList.Count; ++index) {
        var item = theList[index];
        var currentOrdinal = (int)item.Action;

        if(currentOrdinal < previousOrdinal) {
            return false;
        }

        previousOrdinal = currentOrdinal;
    }

    return true;
}

或者你可以使body成为一个参数(在这种情况下,循环变量的名称也应该是一个参数):

apply {vals {foreach a $vals {puts $a}}} {1 2 3 4 5}

如果你打电话给apply {{varName vals body} {foreach $varName $vals $body}} a {1 2 3 4 5} {puts $a} 或其他东西,它看起来不那么麻烦:

myForeach

您也可以将其设为解释器宏:

set myForeach {{varName vals body} {foreach $varName $vals $body}}
apply $myForeach a {1 2 3 4 5} {puts $a}

文档:applyforeachinterp包,interpputsset

答案 1 :(得分:0)

这不是foreach的当前语义,并且在不久的将来不太可能发生变化,因为它会对许多人的现有代码产生严重影响。特别是,目前许多人使用:

foreach {a b c d} $someList break

而不是:

lassign $someList a b c d

因为那是在Tcl 8.4之前和之前的工作,因此他们没有更新他们的编码风格。