proc局部变量如何干扰全局变量
How come a proc local variable interferes with global variable
我用的是TCL 8.6
代码如下:
proc unpack_list {list1 list2} {
set i 0
foreach e $list2 {
puts "globals=[info globals $e]"
global $e
set $e [lindex $list1 $i]
incr i
}
}
set l1 [list 10 20 30 40]
set l2 [list a b c e]
unpack_list $l1 $l2
puts $a
puts $b
puts $c
puts $e
puts [info globals ]
运行 代码失败:
globals=
globals=
globals=
globals=
variable "e" already exists
while executing
"global $e"
(procedure "unpack_list" line 5)
invoked from within
"unpack_list $l1 $l2"
(file "tmp/1.tcl" line 13)
问题出在这一行:
set l2 [list a b c e]
如果我将 "e" 更改为 "ee",脚本运行正常:
globals=
globals=
globals=
globals=
10
20
30
40
tcl_rcFileName tcl_version argv0 argv tcl_interactive a ee b c auto_path env tcl_pkgPath tcl_patchLevel l1 argc l2 tcl_library tcl_platform
我的问题是:proc里面的变量"e"在全局命名空间中不存在,怎么会干扰到全局变量"e"?
如果您阅读 global
命令的说明,它指出该命令创建一个链接到全局变量的局部变量。错误消息讲述了这个故事。局部变量已经存在并且 global
拒绝更改其引用。否则会使局部变量神奇地改变值。
要完成您似乎想要的,您可以使用 upvar
命令。试试这个版本的 unpack_list 命令:
proc unpack_list {list1 list2} {
foreach v $list1 e $list2 {
upvar #0 $e var
set var $v
}
}
这将永远不会导致全局变量名和局部变量名之间的冲突。
我用的是TCL 8.6
代码如下:
proc unpack_list {list1 list2} {
set i 0
foreach e $list2 {
puts "globals=[info globals $e]"
global $e
set $e [lindex $list1 $i]
incr i
}
}
set l1 [list 10 20 30 40]
set l2 [list a b c e]
unpack_list $l1 $l2
puts $a
puts $b
puts $c
puts $e
puts [info globals ]
运行 代码失败:
globals=
globals=
globals=
globals=
variable "e" already exists
while executing
"global $e"
(procedure "unpack_list" line 5)
invoked from within
"unpack_list $l1 $l2"
(file "tmp/1.tcl" line 13)
问题出在这一行:
set l2 [list a b c e]
如果我将 "e" 更改为 "ee",脚本运行正常:
globals=
globals=
globals=
globals=
10
20
30
40
tcl_rcFileName tcl_version argv0 argv tcl_interactive a ee b c auto_path env tcl_pkgPath tcl_patchLevel l1 argc l2 tcl_library tcl_platform
我的问题是:proc里面的变量"e"在全局命名空间中不存在,怎么会干扰到全局变量"e"?
如果您阅读 global
命令的说明,它指出该命令创建一个链接到全局变量的局部变量。错误消息讲述了这个故事。局部变量已经存在并且 global
拒绝更改其引用。否则会使局部变量神奇地改变值。
要完成您似乎想要的,您可以使用 upvar
命令。试试这个版本的 unpack_list 命令:
proc unpack_list {list1 list2} {
foreach v $list1 e $list2 {
upvar #0 $e var
set var $v
}
}
这将永远不会导致全局变量名和局部变量名之间的冲突。