<!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>