您在这里将数组与列表混淆了。
在 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”等。文件名以及连接的项目名称和项目 ID。文字字符串“$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
在这种情况下使用 a 有点多余,因为您所做的只是使用键值列表初始化它(dict
在更现代的 tcl 版本中也称为 a。顺便说一句,您使用的是什么版本的 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 默认情况下不会将全局变量导入函数。因此变量ItemName
和ItemId
不存在于B
. 您要么需要通过以下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
. 照原样,dicts 不会影响上面给出的代码,但会影响代码调用A
。如果您打算使用 dicts,那么您可以将lappend
上面的调用替换为dict append
. 但是旧版本的 tcl 没有字典。