2017-01-17 78 views
0

我正在通过Tcl tutorial和lappend操作符返回意外的结果。Tcl lappend返回意外的结果

我在F5负载平衡硬件的命令行界面上运行这个。下面是相关信息:

~ \# cat /proc/version 
    Linux version 2.6.32-431.56.1.el6.f5.x86_64 ([email protected]) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC)) #1 SMP Wed Jun 8 11:41:48 PDT 2016 

% puts $tcl_version 
8.5 

我试图可变编组,我能想到的每一个排列,而我仍然无法得到我期望的结果。看起来好像存在一个缓冲区,它保留了命令的所有结果:'puts'命令并在'lappend'命令中使用它。这是我执行的几行。前几个'放'只是表明没有任何初始化:

% puts $l1 

can't read "l1": no such variable 

% puts $l2 

can't read "l2": no such variable 

% puts $l3 

can't read "l3": no such variable 

% puts $l4 

can't read "l4": no such variable 

% puts $l5 

can't read "l5": no such variable 

% set l1 { {item 1} {item 2} {item 3} } 

{item 1} {item 2} {item 3} 

% set l2 { {item 4} {item 5} {item 6} } 

{item 4} {item 5} {item 6} 

% set l3 [concat $l1 $l2] 

{item 1} {item 2} {item 3} {item 4} {item 5} {item 6} 

#things working as expected here 
% puts $l3 

{item 1} {item 2} {item 3} {item 4} {item 5} {item 6} 

#this is where things start to get squirrelly. I would expect this to return the result of $l1 concat with $l2 and the result stored in $l1 
% lappend $l1 $l2 

{ {item 4} {item 5} {item 6} } 

#as you can see, it appears to return the second argument when that argument is a list. 
% lappend $l2 $l1 

{ {item 1} {item 2} {item 3} } 

# $l1 remains unchanged. at the very least, according to the documentation, 
# I would expect that second item would be treated as a single entity 
# when it is a list, and that the fourth item in '% lappend $l2 $l1' would be $l1 
% puts $l1 

{item 1} {item 2} {item 3} 

#neither $l2 nor $l1 are modified as the result of the 'lappend' command. 
% puts $l2 

{item 4} {item 5} {item 6} 

#more squirrelly-ness. when the arguments being passed are individual, it seems as though the last call to 'puts' is what 'lappend' uses for its first argument. this is confirmed on the last 3 commands below. **strong text** 
% lappend $l1 "a" "b" "c" 

{ {item 4} {item 5} {item 6} } a b c 

% puts $l1 

{item 1} {item 2} {item 3} 

% lappend "$l1" "$l2" 

**{ {item 4} {item 5} {item 6} } a b c { {item 4} {item 5} {item 6} }** 

% puts $l1 

{item 1} {item 2} {item 3} 

% puts $l2 

{item 4} {item 5} {item 6} 

% set l4 [lappend $l1 $l2] 

**{ {item 4} {item 5} {item 6} } a b c { {item 4} {item 5} {item 6} } { {item 4} 
{item 5} {item 6} }** 

% puts $l4 

{ {item 4} {item 5} {item 6} } a b c { {item 4} {item 5} {item 6} } { {item 4} 
{item 5} {item 6} } 

# confirmed. 'lappend' is using last call to 'puts' as its argument for it's first argument. this can't be intended behavior right? 
% puts $l1 
{item 1} {item 2} {item 3} 
% set l5 [lappend $l2 "a" "b" "c"] 
{ {item 1} {item 2} {item 3} } a b c 
% puts $l2 
{item 4} {item 5} {item 6} 

我无法想象这种行为是有意的。

以下是我想象这应该工作:

#should return something like [$list1, [$list2]] or something like concat $list1 $list2 
% lappend $list1 $list2 

#should return each item concatenated to the end of $list1 
% lappend $list1 "a" "b" "c" 

如果答案是lappend不修改的第一个参数的地方,我必须使用一套命令来保存lappend结果命令,那很好;然而,低调的指挥似乎并没有一贯的行为。

在此先感谢您的帮助/见解。

+0

您正在调用未定义的行为。当你运行'lappend $ l1 $ l2'时,'lappend'需要一个可写变量作为它的第一个参数,但是你给它一个只读变量。如果它是'lappend l1 $ l2'(注意'l1'中缺少'$'),它将按预期工作。 'concat $ l1 $ l2'等价于'lappend''$ l1 $ l2'。 – alvits

+0

真棒。谢谢。这是一个与空字符串一个整洁的小技巧。 –

+0

这不是一个空字符串。这是一个名为''''的变量。 Tcl不使用单引号引用任何内容。 –

回答

2

lappend $l1 $l2将l2的内容追加到变量NAMED的内容l1。您需要lappend l1 $l2,与您通过set l1 whatever设置变量的方式大致相同,而不是set $l1 whatever

+0

啊。知道了谢谢。它有点像C风格的指针。我想要列表本身,而不是列表的内容? –

+0

@JoeGuichebarou因为您正在修改它,所以您希望_variable_保存列表,而不是变量中的列表_value_。 –

2

lappend将变量名称作为其第一个参数,而不是列表。 在这种情况下:

set l1 [list a b c] 
    lappend $l1 x 
    puts [set {a b c}] 
    # returns: x 

x被附加到名为{a b c}变量。

相反,使用变量名作为第一个参数lappend:

set l1 [list a b c] 
    set l2 [list d e f] 
    lappend l1 {*}$l2 
    # result: a b c d e f 

的一般规则要记住的是,如果一个Tcl命令修改其参数,传递变量名。如果Tcl命令不修改其参数,则传递值(此规则对阵列不起作用)。

参考文献:lappend

+0

不幸的是,该教程没有对其语法规范做出适当的区分。我认为目前,您还需要拉起手册页,以便您可以看到正确的语法。还有其他教程可用。 –

+0

真棒。谢谢。巨大的帮助。 –