upvar

Команда создает связи между переменными различных уровней стека.

СИНТАКСИС

      upvar ?level? otherVar myVar ?otherVar myVar...?
    

ОПИСАНИЕ

Команда позволяет одной или больше локальным переменным текущей процедуры ссылаться на переменные процедуры, стоящей выше в стеке, или на глобальные переменные. Аргумент level может иметь те же формы, что и в команде uplevel, или быть опущен, если первый символ в первой из otherVar отличен от цифры и от # (значение по умолчанию 1). Для каждой пары аргументов otherVar myVar команда позволяет сделать переменную с именем otherVar из указанного уровня стека (локальную переменную одной из вызывающих процедур или глобальную переменную, если level равно #0) видимой в исполняемой процедуре под именем myVar. Переменная с именем otherVar не обязана существовать в момент исполнения команды. При необходимости она будет создана при первом использовании переменной myVar. В момент исполнения команды не должно быть доступной переменной myVar. Переменная myVar всегда считается простой переменной (не массивом и не переменной массива). Даже если значение myVar выглядит как имя элемента массива, например, a(b), создается простая переменная. Значение otherVar может быть именем простой переменной, массива или элемента массива. Команда upvar всегда возвращает пустую строку.

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

      proc add2 name { 
      	upvar  x
        set x [expr +2]
      }
    

Процедура add2 вызывается с аргументом, содержащим имя переменной и увеличивает значение этой переменной на два. Хотя тот же результат мог быть получен с помощью команды uplevel, команда upvar позволяет легче работать с переменными из стека вызывающей процедуры.

Команда namespace eval так же, как и вызовы процедур, изменяет контекст, в котором выполняются команды. Для каждой команды namespace eval создается дополнительный уровень в стеке. Соответственно, при указании уровня контекста в стеке каждую вложенную команду namespace eval надо считать наравне с вызовом процедуры. Это относится также к командам uplevel и info level. Например, команда info level 1 вернет список, описывающий самую верхнюю выполняемую команду, которая является либо вызовом процедуры, либо командой namespace eval. Независимо от использования команда namespace eval команда uplevel #0 выполнит соответствующий скрипт на уровне глобальных переменных (в глобальном пространстве имен).

Если переменная, созданная с помощью команды upvar, удаляется (например, если добавить в процедуру add2 строку unset x), то реально будет удалена переменная, связанная с x, а не сама переменная x. Нет никакого способа удалить созданные таким образом переменные, кроме как выйти из процедуры, в которой они были созданы. Тем не менее, возможно связать переменную верхнего уровня с другой локальной переменной, выполнив еще одну команду upvar.

ОШИБКИ

Если otherVar есть элемент массива, то отслеживание массива в целом, заданной командой trace, не сработает при действиях с myVar (однако, если отслеживание было задано на отдельный элемент массива, оно сработает). В частности, изменения, сделанные с помощью myVar в массиве env, не будут корректно переданы подпроцессу.