<!DOCTYPE HTML PUBLIC -//W3C//DTD HTML 4.01 Transitional//EN> <html> <head> <title>upvar</title> </head> <body> <h1>upvar</h1> <p>Команда создает связи между переменными различных уровней стека.</p> <h2>СИНТАКСИС</h2> <pre> <strong>upvar</strong> ?<em>level</em>? <em>otherVar</em> <em>myVar</em> ?<em>otherVar</em> <em>myVar</em>...? </pre> <h2>ОПИСАНИЕ</h2> <p>Команда позволяет одной или больше локальным переменным текущей процедуры ссылаться на переменные процедуры, стоящей выше в стеке, или на глобальные переменные. Аргумент <em>level</em> может иметь те же формы, что и в команде <a href=uplevel.html><strong>uplevel</strong></a>, или быть опущен, если первый символ в первой из <em>otherVar</em> отличен от цифры и от # (значение по умолчанию 1). Для каждой пары аргументов <em>otherVar</em> <em>myVar</em> команда позволяет сделать переменную с именем <em>otherVar</em> из указанного уровня стека (локальную переменную одной из вызывающих процедур или глобальную переменную, если <em>level</em> равно #0) видимой в исполняемой процедуре под именем <em>myVar</em>. Переменная с именем <em>otherVar</em> не обязана существовать в момент исполнения команды. При необходимости она будет создана при первом использовании переменной <em>myVar</em>. В момент исполнения команды не должно быть доступной переменной myVar. Переменная <em>myVar</em> всегда считается простой переменной (не массивом и не переменной массива). Даже если значение <em>myVar</em> выглядит как имя элемента массива, например, a(b), создается простая переменная. Значение <em>otherVar</em> может быть именем простой переменной, массива или элемента массива. Команда <strong>upvar</strong> всегда возвращает пустую строку.</p> <p>Команда upvar позволяет упростить передачу параметра по ссылке, а также упрощает создание новых управляющий конструкций. Например, рассмотрим следующую процедуру:</p> <pre> proc add2 name { upvar x set x [expr +2] } </pre> <p>Процедура <strong>add2</strong> вызывается с аргументом, содержащим имя переменной и увеличивает значение этой переменной на два. Хотя тот же результат мог быть получен с помощью команды uplevel, команда <strong>upvar</strong> позволяет легче работать с переменными из стека вызывающей процедуры.</p> <p>Команда <a href=namespace.html#eval><strong>namespace eval</strong></a> так же, как и вызовы процедур, изменяет контекст, в котором выполняются команды. Для каждой команды <a href=namespace.html#eval><strong>namespace eval</strong></a> создается дополнительный уровень в стеке. Соответственно, при указании уровня контекста в стеке каждую вложенную команду <a href=namespace.html#eval><strong>namespace eval</strong></a> надо считать наравне с вызовом процедуры. Это относится также к командам <a href=uplevel.html><strong>uplevel</strong></a> и <a href=info.html#level><strong>info level</strong></a>. Например, команда <strong><a href=info.html#level>info level</a> 1</strong> вернет список, описывающий самую верхнюю выполняемую команду, которая является либо вызовом процедуры, либо командой <a href=namespace.html#eval><strong>namespace eval</strong></a>. Независимо от использования команда <a href= namespace.html#eval><strong>namespace eval</strong></a> команда <strong>uplevel #0</strong> выполнит соответствующий скрипт на уровне глобальных переменных (в глобальном пространстве имен).</p> <p>Если переменная, созданная с помощью команды <strong>upvar</strong>, удаляется (например, если добавить в процедуру <strong>add2</strong> строку unset x), то реально будет удалена переменная, связанная с x, а не сама переменная x. Нет никакого способа удалить созданные таким образом переменные, кроме как выйти из процедуры, в которой они были созданы. Тем не менее, возможно связать переменную верхнего уровня с другой локальной переменной, выполнив еще одну команду <strong>upvar</strong>.</p> <h2>ОШИБКИ</h2> <p>Если <em>otherVar</em> есть элемент массива, то отслеживание массива в целом, заданной командой <a href= trace.html><strong>trace</strong></a>, не сработает при действиях с <em>myVar</em> (однако, если отслеживание было задано на отдельный элемент массива, оно сработает). В частности, изменения, сделанные с помощью <em>myVar</em> в массиве <a href=tclvars.html#env><strong>env</strong></a>, не будут корректно переданы подпроцессу. </p> </body> </html>