我有以下代码:
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 脚本时,“set d1 $ar($key)”行失败。错误消息是“无法读取“ar(a1)”:变量不是数组”。您能否建议导致错误的原因以及如何解决该错误。
当你使用语法时$ar($key)
,您正在查找密钥$key
在数组中ar
并返回其值。这就是 Tcl 的工作方式,它采用基本语言语法。但是,您正在使用ar
变量来保存标量值,而不是数组(两者是完全地分离;数组不是值,但列表和字典是)。这就是您收到错误消息的原因。
要从变量中命名的数组中读取,您需要使用更长的语法,以便替换变量名称,然后从该变量中读取(Tcl 默认情况下不会为您执行此操作,因为它相当如果您没有为此做好准备,则很危险)或者您需要为指定的数组变量创建别名。
双替换通过set
set d1 [set ${ar}($key)]
这有效是因为$…
实际上(在幕后)是一个别名set
有一个参数。 (好吧,除了它不actually调用命令;它们都调用相同的 C API。)我们使用${...}
形式来限制初始的内容$
用作其变量名称。请注意,如果您将数组元素名称放入ar
,你会得到奇怪的结果。
给数组或元素起别名
upvar 0 $ar theAlias
set d1 $theAlias($key)
The upvar
命令将变量链接在一起,特别是与0
作为它的第一个参数,它为当前作用域中的变量设置别名。通过建立theAlias
作为实际数组的固定别名(由$ar
),然后我们就可以像普通数组一样访问它。您还可以直接为元素添加别名:
upvar 0 ${ar}($key) theAlias
set d1 $theAlias
请注意与使用相同的语法set
上面的解决方案;我们想要元素的名称,而不是读取它。 (警告:不要为全局元素添加别名env
大批;耦合到系统环境变量的代码不能以友好的方式使用别名。)
使用的主要问题upvar
是你无法转身theAlias
返回到非别名变量(尽管您可以通过调用来重新定位别名)upvar
再次)除了丢弃当前堆栈帧(对于过程体来说微不足道,对于命名空间来说也不太难namespace delete
,但全局命名空间有问题,因为删除会终止整个 Tcl 解释器)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)