Arrays 不覆盖数组的现有值的set函数
我经常看到这样的全局变量构造:Arrays 不覆盖数组的现有值的set函数,arrays,tcl,Arrays,Tcl,我经常看到这样的全局变量构造: global var if {![info exists var]} { set var "Some default value" } 或对于阵列: global array if {![info exists array(key)]} { set array(key) "Some default value" } 写起来有点长。所以我写了一个非常基本的集合函数: proc set_if_not_exist { name value } {
global var
if {![info exists var]} {
set var "Some default value"
}
或对于阵列:
global array
if {![info exists array(key)]} {
set array(key) "Some default value"
}
写起来有点长。所以我写了一个非常基本的集合函数:
proc set_if_not_exist { name value } {
if {![info exist $name ] } {
set $name $value
}
}
这很好,但当我尝试对数组执行同样的操作时,情况会变糟:
代码
#! /usr/bin/tclsh
proc my_set { name key value } {
global $name
if { ! [ info exist $name($key) ] } {
set $name($key) $value
}
}
global my_array
set my_array(a) "a set value"
my_set my_array a "OK"
my_set my_array b "OK"
puts "a: $my_array(a)\n"
puts "b: $my_array(b)\n"
我想要的是:
a: a set value
b: OK
我得到了什么
can't read "name(a)": variable isn't array
while executing
"info exist $name($key) "
(procedure "my_set" line 4)
invoked from within
"my_set my_array a "OK""
因此:从函数内部设置数组的惯用语法是什么?请尝试以下方法
proc my_set { name key value } {
global $name
if { ! [ info exist [set name]($key) ] } {
set $name($key) $value
}
}
我找到了我想要的方法:需要使用
upvar
:
proc my_set { name key value } {
global $name
upvar 1 $name arr
if { ! [ info exist arr($key) ] } {
set arr($key) $value
}
}
你很接近你自己找到的答案。但如果您将过程编写为:
proc my_set {name value} {
upvar 1 $name var
if {![info exist var]} {
set var $value
}
}
然后,您可以简单地对常规变量和数组元素使用相同的过程,就像您习惯于使用set命令一样:
my_set my_array(a) "a set value"
my_set my_array(a) "OK"
my_set my_array(b) "OK"
然后parray my_数组
给出:
my_array(a) = a set value
my_array(b) = OK
只有当从全局命名空间调用
my_set
过程时,upvar 1
的解决方案才有效。当从另一个过程调用此过程时,它们将失败。正确而简单的解决方案是:
proc my_set { name key value } {
upvar #0 $name arr
if { ![info exist arr($key)] } {
set arr($key) $value
}
}
如果使用
upvar
访问其作用域中的数组,则不需要global