Помимо использования proc, вы можете вместо этого использовать блок кода. Есть несколько вариантов этого. первый - самый очевидный, просто eval
его.
set strategy {
puts $x
}
set x "Hello"
eval $strategy
unset x
Это работает, но есть несколько минусов. Во-первых, очевидно, что обе части кода должны сговориться с использованием общего именования аргументов. Это заменяет одну головную боль в пространстве имен (procs) другой (localals), и это, вероятно, на самом деле хуже .
Менее очевидно, что eval намеренно интерпретирует свой аргумент без компиляции байт-кода. Это потому, что предполагается, что eval будет вызываться с динамически генерируемыми, обычно уникальными аргументами, и компиляция в байт-код будет неэффективной, если байт-код будет использоваться только один раз, по сравнению с простой интерпретацией блока немедленно. Это легче исправить, поэтому вот идиома:
set x "Hello"
if 1 $strategy
unset x
if
, в отличие от eval
, компилирует и кэширует свой блок кода. Если в блоке $strategy
только одно или несколько различных возможных значений, то это работает очень хорошо.
Это совсем не помогает в поспешности передачи аргументов в блок с локальными переменными. Существует множество способов, например, подстановок таким же образом, как tk выполняет подстановку аргументов команды с %
. Вы можете попробовать сделать некоторые хакерские вещи, используя uplevel
или upvar
. Например, вы можете сделать это:
set strategy {
puts %x
}
if 1 [string map [list %% % %x Hello] $strategy]
Если вероятность того, что передаваемые аргументы не сильно изменятся, это хорошо с точки зрения компиляции байт-кода. С другой стороны, если аргумент часто меняется, вы должны использовать eval
вместо if 1
. В любом случае, это не намного лучше с точки зрения аргументов. Вероятность путаницы в отношении того, что передано, а что нет, меньше, потому что вы используете специальный синтаксис. Также это полезно, если вы хотите использовать подстановку переменных перед возвратом блока кода: как в set strategy "$localvar %x"
.
К счастью, tcl 8.5 имеет истинных анонимных функций , использующих команду apply
. Первым словом в команде apply будет список аргументов и тела, как если бы эти аргументы для proc
были исключены. Остальные аргументы передаются анонимной команде в качестве аргументов немедленно.
set strategy [list {x} {
puts $x
}]
apply $strategy "Hello"