Как прочитать имя переменной, в которой хранится значение
Пример программы TCL:
proc fun { x } {
puts "$$x = $x"
}
set a 10
fun $a
В этой вышеупомянутой программе, которая печатает вывод как $10 = 10
Но я бы хотел получить a = 10
имеет выход. Переменная, которая передает значения, должна быть прочитана, а также соответствующие значения. Есть ли способ прочитать имя переменной.
4 ответа
proc fun name {
upvar 1 $name var
puts "$name = $var"
}
set a 10
fun a
Команда upvar берет имя и создает псевдоним переменной с этим именем.
Документация: проц, ставит, устанавливает, упвар
Если у вас есть поддерживаемая в настоящее время версия Tcl (8.5 или 8.6), вы можете использовать info frame -1
узнать некоторую информацию о звонящем. В нем есть всякая информация, но мы можем сделать разумное приближение следующим образом:
proc fun { x } {
set call [dict get [info frame -1] cmd]
puts "[lindex $call 1] = $x"
}
set a 10
fun $a
# ==> $a = 10
fun $a$a
# ==> $a$a = 1010
Теперь использование lindex
там строго неправильно; это код Tcl, а не список (и вы увидите разницу, если будете использовать сложную подстановку команд). Но если вы когда-либо используете довольно простое слово, оно работает достаточно хорошо.
% set x a
a
% set a 10
10
% eval puts $x=$$x
a=10
% puts "$x = [subst $$x]"
a = 10
% puts "$x = [set $x]"
a = 10
%
Если вы передаете переменную в процедуру, вы должны полагаться на upvar
,
Очевидно, есть другой способ, который я нашел на других страницах форума.
upvar работает быстрее, если доступ/использование переменной более одного раза, в противном случае, если используется только один раз и это глобальная переменная "[set ::[имя набора]]" может быть лучше.
Приведенная ниже процедура использует глобальное пространство имен для проверки его существования и устанавливает значение по умолчанию, если нет. Печатает текущее значение.
proc setvardefault {name value} {
# if global var name does not exist set it to value
if {![info exists ::[set name] ]} { set ::[set name] $value }
# print the current value of global var name
puts "# INFOCHECK $name : [set ::[set name]]"
#upvar 1 $name var
#puts "# INFOCHECK $name : $var"
}
Для печатной части нужны только путы.