Разница между упвар 0 и упвар 1 в TCL

Может кто-нибудь, дайте мне знать разницу между upvar 0 а также upvar 1 в TCL, как мы можем использовать в режиме реального времени. Пожалуйста, если кто-то объяснит с примером, это делает меня более ясным.

3 ответа

Когда вы вызываете кучу процедур, вы получаете стек фреймов стека. Это во имя. Мы могли бы визуализировать это так:

ABC 123 456
   bcd 321 456
      кд 654 321

Хорошо, у нас есть abc призвание bcd призвание cde, Просто.

0 а также 1 в upvar Скажите, сколько уровней нужно поднять в стеке при поиске переменной для ссылки. 1 означает перейти на один уровень вверх (т. е. к абоненту текущего кадра), скажем, из cde в bcd в нашем примере 2 будет идти от cde вплоть до abc а также 3 вплоть до глобального уровня оценки, где выполняются общие сценарии и обратные вызовы. 0 это частный случай этого; это значит сделать поиск в текущем стековом фрейме. Также есть возможность использовать индексирование из базы стека, поставив # перед именем, так #0 указывает на глобальный фрейм, #1 первое, что он называет.

Наиболее распространенное использование upvar является upvar 1 (и если вы пропустите уровень, это то, что он делает). upvar 0 действительно используется только тогда, когда вы хотите получить другое (обычно более удобное для работы) имя для переменной. Следующий наиболее распространенный upvar #0, хоть global это гораздо более распространенное сокращение (которое соответствует неквалифицированным частям имени для вашего удобства). Другие формы редки; например, upvar 2 обычно является признаком действительно запутанного и запутанного кода, и вряд ли кто-либо когда-либо использовал upvar #1 до сопрограмм Tcl 8,6. Я никогда не видел upvar 3 или же upvar #2 в дикой природе (хотя вычисленные индикаторы уровня присутствуют в некоторых объектных системах для Tcl).

Пример upvar 1 - передать переменную по имени:

proc mult-by {varName multiplier} {
    upvar 1 $varName var
    set var [expr {$var * $multiplier}]
}

set x 2
mult-by x 13
puts "x is now $x"
# x is now 26

Пример upvar 0 - упростить имя переменной:

proc remember {name contents} {
    global my_memory_array
    upvar 0 my_memory_array($name) var
    if {[info exist var]} {
        set var "\"$var $contents\""
    } else {
        set var "\"$name $contents\""
    }
}

remember x 123
remember y 234
remember x 345
remember y 456
parray my_memory_array
# my_memory_array(x) = ""x 123" 345"
# my_memory_array(y) = ""y 234" 456"

В отличие от upvar 1, upvar 0 создает псевдоним для переменной. Например:

    set a 4 
proc upvar1 {a} {
upvar 1 a b
incr a 4
incr b 3
puts "output is $a $b"
}
proc upvar0 {a} {
upvar 0 a b
incr a 4
incr b 3
puts "output is $a $b"
}
upvar1 $a
puts "in global frame value of a is  $a"

set a 4
upvar0 $a
puts "in global frame value of a is  $a"

Выход:

output is 8 7
in global frame value of a is  7
output is 11 11
in global frame value of a is  4

Хорошо, я думаю, что пример прояснит разницу:

Допустим, у нас есть функция test_upvar1:

proc test_upvar1 {} {
    upvar 1 a b
    incr b
}

И функция test_upvar0:

proc test_upvar0 {} {
    upvar 0 a b
    incr b
}

Теперь мы устанавливаем переменную a и вызываем обе функции, чтобы увидеть, что происходит:

set a 5
test_upvar1

Это вернется 6

set a 5
test_upvar0

Вернется 1

Это происходит потому, что мы выбираем ноль и один наш кадр выполнения 0 ссылок в том же кадре выполнения 1 кадр выше.

Смотрите http://wiki.tcl.tk/1508

Другие вопросы по тегам