2017-01-17 76 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

真棒。謝謝。巨大的幫助。 –