我经常看到这样的全局变量构造:
global var
if {![info exists var]} {
set var "Some default value"
}
或者对于数组:
global array
if {![info exists array(key)]} {
set array(key) "Some default value"
}
写的时间有点长。所以我写了一个非常基本的set函数:
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""
因此:从函数内部设置数组的惯用语法是什么?
答案 0 :(得分:2)
您很接近找到自己的答案。但是,如果您将proc编写为:
proc my_set {name value} {
upvar 1 $name var
if {![info exist var]} {
set var $value
}
}
然后,您可以简单地对正则变量和数组元素使用相同的proc,就像您习惯使用set命令一样:
my_set my_array(a) "a set value"
my_set my_array(a) "OK"
my_set my_array(b) "OK"
然后parray my_array
给出:
my_array(a) = a set value
my_array(b) = OK
答案 1 :(得分:0)
尝试如下。
proc my_set { name key value } {
global $name
if { ! [ info exist [set name]($key) ] } {
set $name($key) $value
}
}
答案 2 :(得分:0)
我找到了实现自己想要的方式:需要使用upvar
:
proc my_set { name key value } {
global $name
upvar 1 $name arr
if { ! [ info exist arr($key) ] } {
set arr($key) $value
}
}
答案 3 :(得分:0)
只有从全局名称空间调用upvar 1
过程时,my_set
的解决方案才起作用。当从另一个过程调用此过程时,它们将失败。正确和简单的解决方案是:
proc my_set { name key value } {
upvar #0 $name arr
if { ![info exist arr($key)] } {
set arr($key) $value
}
}