Tcl: оценивать значение переменной при передаче аргумента в класс - PullRequest
0 голосов
/ 04 марта 2020

У меня есть такой код

oo::class create class_test {
    variable title_text
    variable result
    method title {t} {
        set title_text $t
        set result [format "%-6s %-6s" {*}$title_text]
    }
    method print {} {
        return $result
    }
}

set a "abcde"
set b "fghij"
class_test create foo
foo title {"$a" "$b"}
puts [foo print]

Реальный вывод

$a     $b

В то время как ожидаемый вывод

abcde  efghi

Может кто-нибудь помочь это исправить?

Ответы [ 3 ]

2 голосов
/ 04 марта 2020

Измените

foo title {"$a" "$b"}

на

foo title [list $a $b]

, чтобы переменные были заменены их значениями.

1 голос
/ 04 марта 2020

Вы хотите расширить подстановки внутри строки {, заключенной в скобки } (логически) после того, как она написана в сценарии. Обычно это не рекомендуется (не тогда, когда вы можете правильно построить аргументы с list), но вы можете сделать это.

method title {t} {
    set title_text [lmap value $t {
        uplevel 1 [list subst $value]
    }]
    set result [format "%-6s %-6s" {*}$title_text]
}

Мы выполняем преобразование для каждого слова в аргумент (lmap) и преобразование должно применить subst к нему, что должно быть сделано в контексте вызывающего (uplevel 1). Использование list позволяет гарантировать создание сценария без подстановки во внешнем контексте, очень настоятельно рекомендуемая практика .


Особенностью TclOO является то, что вам не нужно принимать специальные меры предосторожности, чтобы использовать uplevel (или upvar) при его использовании, в отличие от некоторых других более старых объектных систем для Tcl. Это делает такие вещи в методе не более сложным, чем в обычной процедуре. Это верно даже при наличии наследства.

0 голосов
/ 10 марта 2020

Может ли кто-нибудь помочь исправить это?

Я не понимаю, почему вы сначала упаковываете ссылки на переменные в одно значение, а затем заменяете их на более высокий уровень. Кроме того, число аргументов-значений для format кажется фиксированным. Почему бы просто не использовать два отдельных формальных параметра для вашего title метода и использовать их напрямую?

method title {v1 v2} {
    set result [format "%-6s %-6s" $v1 $v2]
}

Затем просто вызвать его так:

foo title $a $b

Обновить

для создания заголовка различной длины

, тогда лучше использовать args, как это?

method title {args} {
    set result [format [join [lrepeat [llength $args] "%-6s"] " "] {*}$args]
}

args - это естественный способ иметь метод ( pro c) с переменными аргументами в Tcl.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...