我有以下代码:
set arr1(a1) t1
set arr2(a2) t2
set l1 {}
lappend l1 arr1
lappend l1 arr2
set arr3(a3) $l1
foreach names [array names arr3] {
set value $arr3($names)
puts "names = $names, value = $value"
foreach ar $value {
if {[array exists $ar]} {
puts "$ar is an array"
foreach {key val} [array get $ar] {
set d1 $ar($key)
puts "ar key = $key value = $val "
}
}
}
}
但是当我运行Tcl脚本的失败为线“组D1 $ AR($键)”。 的错误味精是“不能读取‘芳(A1)’:变量不是阵列”。 你可以请建议是什么原因造成的错误,我该如何解决一样。
当您使用语法$ar($key)
,您所查询的关键$key
在阵列ar
和返回它的值。 这是Tcl的是如何定义的工作,它在基本的语言语法。 然而,您使用的ar
变量来保存的标量值,而不是一个阵列(两者是完全独立的;数组是没有价值,虽然列表和字典是)。 这就是为什么你得到错误信息。
若要从一个变量命名的数组读取,您可能需要使用一段较长的语法,让你用变量名称,然后从该变量读取(TCL默认不为你做这个,因为这是相当危险的,如果你不为它做准备),或者你需要做的别名命名的数组变量。
通过双替换set
set d1 [set ${ar}($key)]
这工作,因为$…
真的(引擎盖下)的别名set
有单独的参数。 (当然,除了它实际上并没有调用命令,它们都调用同一个C API)。我们使用${...}
形式来限制初始$
使用它作为变量名。 请注意,如果你在把一个数组元素的名称ar
,你会得到从这个奇怪的结果。
混叠Array或一个Element
upvar 0 $ar theAlias
set d1 $theAlias($key)
所述upvar
命令链接变量一起,尤其当用于0
作为第一个参数,它别名在当前范围的变量。 通过建立theAlias
作为固定别名实际阵列(一个名为$ar
),我们就可以访问它就像一个正常的阵列。 同时,你可以别名直接给一个元素:
upvar 0 ${ar}($key) theAlias
set d1 $theAlias
注意相同的语法与所使用的set
以上溶液; 我们需要的元素的名称,而不是阅读。 (警告:不要别名全球的元素env
。数组;联接到系统环境变量不与别名友好的方式工作的代码)
使用的主要问题upvar
是,你不能把theAlias
回非别名的变量(尽管你可以重新定位,通过调用别名upvar
再次)其他比扔掉当前栈帧(平凡的过程体,不太硬了通过一个命名空间namespace delete
,但随着全球命名空间删除终止整个Tcl解释问题)。