你在這裏混淆了數組與列表。
在tcl中,您不能將數組傳遞或從函數返回。另外,tcl使用術語「數組」來表示C++調用「映射」或Perl和Ruby調用「哈希」或Javascript調用「對象」的內容。這個術語來源於這樣一個事實,即所有這些東西在計算機科學中統稱爲「關聯陣列」。所以tcl中的「數組」是鍵值對,而不是數據序列。
數組通常不會退化爲值(或經驗豐富的tcl程序員稱爲「字符串」)。因此這樣的:
array set tcArrayName {$fileName $tcSpec};
return $tcArrayName;
生成語法錯誤:
can't read "tcArrayName": variable is array
實際上,你可以變質的數組的內容到一個值,你就可以回來。但是你必須通過[array get]
命令手動:
return [array get tcArrayName]
上面的命令將返回tcArrayName
陣列的內容在兩個元素的列表的形式:
"$fileName $tcSpec"
這也恰好是一個字符串。這就是實際的字符串:字符'$'後面跟着字符'f','i','l','e','N','a','m','e'等等。文件名和連接的項目名稱和項目標識。文字字符串「$ fileName $ tcSpec」。
那是因爲你使用了{}
分組在這行代碼:
array set tcArrayName {$fileName $tcSpec}
在TCL,{xxx}
的工作方式'xxx'
確實在Perl。基本上它是一個不被替換的文字字符串。如果你想TCL做$
替代,那麼你需要使用""
分組:
array set tcArrayName "$fileName $tcSpec"
但這是脆弱的,因爲如果fileName
包含空格,那麼它會破壞代碼。更健壯的方式來做到這一點是:
array set tcArrayName [list $fileName $tcSpec]
但在這種情況下使用array
是有點多餘,因爲你正在做的是有一個鍵值列表(也稱爲dict
更初始化它現代版本的tcl.BTW,你使用的是什麼版本的tcl),然後立即丟棄它,並將它的內容作爲鍵值列表返回。
爲什麼不直接返回鍵值列表:
proc B {fileID} {
set fileName [::getFileName $fileID]; # getFileName returns filename from fileid
set tcName "[set ItemName]_[set ItemId]"
return [list $fileName $tcSpec]
}
但我們仍然不明確。如果您嘗試執行B
你會看到這樣的錯誤:
can't read "ItemName": no such variable
這是因爲TCL默認不導入全局變量到功能。因此,B
中不存在變量ItemName
和ItemId
。您可能需要通過global
命令明確導入:
proc B {fileID} {
global ItemName
global ItemId
# ...
}
或使用完全限定的變量名通過全局命名空間訪問它:
set tcName "[set ::ItemName]_[set ::ItemId]"
所以B
應該是這樣的:
proc B {fileID} {
set fileName [::getFileName $fileID]; # getFileName returns filename from fileid
set tcName "[set ::ItemName]_[set ::ItemId]"
return [list $fileName $tcSpec]
}
這就是B
照顧但A
也有一些問題:
can't read "file1": no such variable
我們需要稍作修改,以訪問變量file1
:
proc A {} {
set lst_A [list];
if {true} { ;# assuming that there will be a valid condition here
lappend lst_A [::B $::file1];
} else {
foreach id $allId {
lappend lst_A [::B $id];
}
}
return $lst_A;
}
像您期望這應該工作。
如果您希望在使用鍵值列表時加快速度,那麼您應該真正閱讀dicts
。因爲,字典不會影響上面給出的代碼,但它確實會影響調用A
的代碼。如果您打算使用dicts,則可以用dict append
替換上面的lappend
調用。但舊版本的tcl沒有字典。
只是一個建議:如果你使用8.6,那麼你可以寫它爲'if {1} {return [list [B $ :: file1]]} else else {return [lmap id $ :: allId {B $ id }]}}' –
是的,但如果你有8.6代替使用'dict append'而不是lmap的foreach會更好,因爲它避免了字典列表閃爍。 – slebetman
感謝您澄清上述問題。儘管我找到了解決我的實際問題的不同方法,但您的答案是使用數組的一個很好的解釋。再次感謝Slebetman。 :) –