我发现我经常想要将值附加到字典列表中,但前提是该值不在列表中。因此,我正在尝试将其分离为一个过程,我无法弄清楚为什么以下代码无法实现此目的:
proc DictAdd {_dictionary key value} {
upvar 1 $_dictionary dictionary
if { $value ni [dict get $dictionary $key] } {
dict lappend dictionary $key $value
}
}
调用此过程将返回以下错误:
can't read "dictionary": no such variable
while executing
"dict get $dictionary $key"
(procedure "DictAdd" line 5)
invoked from within
"DictAdd $files baseline $fileName"
(procedure "getFilesToLoad" line 53)
invoked from within
...
有人可以告诉我这里我做错了什么吗?感谢。
答案 0 :(得分:0)
问题很可能是您所指的字典变量实际上未设置,因此无法读取。试试这个:
proc DictAdd {_dictionary key value} {
upvar 1 $_dictionary dictionary
if {![info exists dictionary]} {
set dictionary [dict create $key [list $value]]
} elseif {$value ni [dict get $dictionary $key]} {
dict lappend dictionary $key $value
}
}
答案 1 :(得分:0)
在调用中
DictAdd $files baseline $fileName
$files
是字典的值,但DictAdd
需要字典变量的名称。如果您改为这样调用它:
DictAdd files baseline $fileName
该命令按设计工作。
BTW:如果你这样定义DictAdd
:
proc DictAdd {_dictionary key value} {
upvar 1 $_dictionary dictionary
if {[dict exists $dictionary $key]} {
dict with dictionary {
upvar 0 $key values
if {$value ni $values} {
lappend values $value
}
}
} else {
dict lappend dictionary $key $value
}
}
如果密钥丢失,则不会收到错误消息(它会在该密钥下添加值)(字典仍需要存在于DictAdd
之外)并且检查/添加代码变得不那么混乱
为什么这个名字?这是因为upvar
的工作原理。该命令采用堆栈级别(在这种情况下1 =调用者的级别)和变量名称(包含在_dictionary
;“文件”中);使用它在执行命令之外定位一个变量,并在执行命令中创建一个本地别名(在本例中命名为dictionary
:files
外部现在与dictionary
里面的变量基本相同)。如果您传递其他内容,例如files
的值,例如{baseline {a b c}}
,upvar
将查找名为{baseline {a b c}}
的变量,并且很可能找不到它。它会创建别名,如果你初始化它,实际上会创建一个在调用者级别调用{baseline {a b c}}
的变量。但是,再次,您将需要使用变量的名称(当然,当您调用命令时,变量的名称可能是另一个变量的值...)。