Невозможно передать переменную в процедуру, используя upvar в Tcl - PullRequest
1 голос
/ 21 октября 2011

Мне нужна процедура, которая сможет получить доступ, прочитать и изменить переменную из пространства имен вызывающей стороны.Переменная называется _current_selection.Я пытался сделать это, используя upvar несколькими различными способами, но ничего не получалось.(Я написал небольшой тестовый процесс только для проверки механизма upvar).Вот мои попытки:


вызов proc:

select_shape $this _current_selection

proc:

proc select_shape {main_gui var_name} {
    upvar  $var_name curr_sel
    puts " previously changed:  $curr_sel"
    set curr_sel [$curr_sel + 1]
}

Для моей второй попытки:

вызов proc:

select_shape $this

proc:

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 ]

4 голосов
/ 21 октября 2011

Я считаю, что bind команды работают в глобальном пространстве имен, так что именно там переменная должна быть найдена.Это может работать:

$this/zinc bind current <Button-1> \
    [list select_shape $this [namespace current]::_current_selection]
3 голосов
/ 21 октября 2011

для работы upvar переменная должна существовать в той области, в которой вы ее вызываете. Учитывайте следующее:

proc t {varName} {
   upvar $varName var
   puts $var
}

#set x 1
t x

Если вы запустите его как есть, вы получите сообщение об ошибке, раскомментируйте строку set x 1 , и она будет работать.

0 голосов
/ 21 октября 2011

В следующем примере я попытался охватить большинство вариантов изменения переменных из другого пространства имен.Это 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
...