Невозможно передать переменную в процедуру, используя upvar в Tcl
Мне нужна процедура, которая сможет получить доступ, прочитать и изменить переменную из пространства имен вызывающей стороны. Переменная называется _current_selection
, Я пытался сделать это с помощью upvar
несколькими разными способами, но ничего не получалось. (Я написал небольшой тестовый прог, просто чтобы проверить upvar
механизм). Вот мои попытки:
вызов к процессу:
select_shape $this _current_selection
прок:
proc select_shape {main_gui var_name} {
upvar $var_name curr_sel
puts " previously changed: $curr_sel"
set curr_sel [$curr_sel + 1]
}
Для моей второй попытки:
вызов к процессу:
select_shape $this
прок:
proc select_shape {main_gui} {
upvar _current_selection curr_sel
puts " previously changed: $curr_sel"
set curr_sel [$curr_sel + 1]
}
Во всех попытках, как только он достигает этой области в коде, он говорит can't read "curr_sel": no such variable
Что я делаю неправильно?
РЕДАКТИРОВАТЬ:
Вызов функции сделан из bind
команда:
$this/zinc bind current <Button-1> [list select_shape $this _current_selection]
Сначала я думал, что это не имеет значения. но, возможно, это так.
3 ответа
Я полагаю, что bind
Команды работают в глобальном пространстве имен, так что именно там переменная должна быть найдена. Это может сработать:
$this/zinc bind current <Button-1> \
[list select_shape $this [namespace current]::_current_selection]
Для работы upvar переменная должна существовать в той области, в которой вы ее вызываете. Учтите следующее:
proc t {varName} {
upvar $varName var
puts $var
}
#set x 1
t x
Если вы запустите его как есть, вы получите сообщение об ошибке, раскомментируйте строку set x 1, и она будет работать.
В приведенном ниже примере я попытался охватить большинство вариантов изменения переменных из другого пространства имен. Это 100% работает для меня. Может быть, это поможет.
proc select_shape {main_gui var_name} {
upvar $var_name curr_sel
puts " previously changed: $curr_sel"
incr curr_sel
}
namespace eval N {
variable _current_selection 1
variable this "some_value"
proc testN1 {} {
variable _current_selection
variable this
select_shape $this _current_selection
puts " new: $_current_selection"
}
# using absolute namespace name
proc testN2 {} {
select_shape [set [namespace current]::this] [namespace current]::_current_selection
puts " new: [set [namespace current]::_current_selection]"
}
select_shape $this _current_selection
puts " new: $_current_selection"
}
N::testN1
N::testN2
#-------------------------------------
# Example with Itcl class
package require Itcl
itcl::class C {
private variable _current_selection 10
public method testC {} {
select_shape $this [itcl::scope _current_selection]
puts " new: $_current_selection"
}
}
set c [C #auto]
$c testC