Что {*} делает в TCL? - PullRequest
       28

Что {*} делает в TCL?

8 голосов
/ 26 февраля 2011

Я использовал некоторые TCL, но эта конструкция ставит меня в тупик.

Когда $ res = "Таблица не существует", что вернет следующий код?

[list [list {*}$res]]

Я знаю, что [list [list $res]] сделает, но дополнительные {*} просто сбивают меня с толку.

Спасибо за помощь.

Ответы [ 3 ]

7 голосов
/ 28 февраля 2011

Когда $ res = "Таблица не существует", что вернет следующий код?

[list [list {*}$res]]

Ну, во-первых, знайте, что [list {*}…] - это конструкция, которая возвращает список слов в многоточии (содержимое переменной res в вашем случае). случается , что в вашем случае чистый эффект - ничто, поскольку входная строка на самом деле также является правильно сформированным списком. Затем он становится единственным аргументом для внешнего list, и в результате мы получаем список из одного элемента, элемент которого содержит список слов Table, does, not и exist в указанном порядке. {Table does not exist}.

Примечания по расширению

Список расширенных словоформ полезен для объединения списков; команда concat делает нечто подобное (но не идентично; в команде concat есть некоторые исторические странности). Таким образом, вы бы объединили два списка следующим образом:

set concatenation [list {*}$list1 {*}$list2]

Также обратите внимание, что расширение (введено в Tcl 8.5) имеет истинный синтаксис , что очень необычно в Tcl. {*} меняет природу следующей замены, так что в результате получается несколько слов вместо одного. Хотя без этого можно обойтись, на самом деле удивительно трудно получить права. Например, без него выше было бы:

set concatenation [eval [linsert $list1 0 list] [lrange $list2 0 end]]

Внедрение расширения значительно сократило количество вызовов до eval, требуемых в большинстве кодов Tcl (преимущество, поскольку его было трудно писать правильно; многие программисты были пойманы этой сложностью). Это оказалось особенно полезным на практике с командой exec; это значительно упрощает работу с glob и auto_execok:

exec {*}[auto_execok $someCmd] $arg1 {*}[glob *.foo]
# Instead of:
#eval [linsert [auto_execok $someCmd] 0 exec] [linsert [glob *.foo] 0 $arg1]
# Or this _wrong_ version:
#eval exec [auto_execok $someCmd] $arg1 [glob *.foo]

Тьфу. Этот последний был немного изнурительным, чтобы писать в форме без расширения, хотя я знаю, что делаю. (Неправильная версия неправильна, потому что она разваливается, если $arg1 содержит метасимволы Tcl…)

5 голосов
/ 26 февраля 2011

Это описано на странице руководства по синтаксису Tcl .Это обсуждается на Tcl wiki .Он был введен в язык в TIP 293 (его предшественником был TIP 157 , где вы можете узнать, как он работает).

По сути, {*}$res разделитстрока в его разделенные пробелами слова.Итак, [list {*}$res] действует так же, как [split $res] (в данном случае).

Конечным результатом является список из одного элемента, список слов в $ res.

3 голосов
/ 26 февраля 2011

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

Посмотрите этот пример, чтобы понять, как это работает:

% set c [list a b]
a b
% set d [list e f]
e f
% set x [list $c {*}$d]
{a b} e f
% set y [lindex $x 2]
f
% set y [lindex $x 1]
e
% set y [lindex $x 0]
a b
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...