Работа с TCL, и я хотел бы реализовать что-то вроде Strategy Pattern. Я хочу перейти в «стратегию» для вывода на печать в функции TCL, поэтому я могу легко переключаться между печатью на экран и печатью в файл журнала. Каков наилучший способ сделать это в TCL?Есть ли у TCL какое-то понятие указателей функций?
ответ
TCL позволяет хранить имя процедуры в переменной, а затем вызывать процедуру с использованием этой переменной; так
proc A { x } {
puts $x
}
set strat A
$strat Hello
будет вызывать ргос A и распечатать Hello
Как насчет использования переменных функций? Я не помню, много TCL (это было в то время как ...), но, может быть, один из них будет делать то, что вам нужно:
- [$ вар param1 param2]
- [$ вар] param1 param2
- $ вар param1 param2
Если я не прав, кто свободен, поправьте меня.
Это последний, который вы должны использовать. – 2008-10-31 14:24:04
Несколько расширен пример того, что было перечислено выше, которые могли бы проиллюстрировать стратегию шаблон более четко:
proc PrintToPDF {document} {
<snip logic>
}
proc PrintToScreen {document} {
<snip logic>
}
proc PrintToPrinter {document} {
<snip logic>
}
set document "my cool formatted document here"
set printMethod "printer"
switch -- $printMethod {
"printer" {
set pMethodName "PrintToPrinter"
}
"pdf" {
set pMethodName "PrintToScreen"
}
"screen" {
set pMethodName "PrintToPDF"
}
}
$pMethodName $document
В дополнение к ответ, показывающий, как вы назначаете процедуру переменной, вы также можете передать имя процедуры в качестве аргумента другой процедуре. Вот простой пример:
proc foo { a } {
puts "a = $a"
}
proc bar { b } {
puts "b = $b"
}
proc foobar { c } {
$c 1
}
foobar foo
foobar bar
Это напечатает а = 1, Ь = 1
Чтобы выяснить, почему метод Джексона работает, помните, что в TCL, все является строкой. Независимо от того, работаете ли вы с литеральной строкой, функцией, переменной или каким бы то ни было, все - это строка. Вы можете передать «указатель функции» так же, как вы можете «указатель данных»: просто используйте имя объекта без ведущего «$».
Помимо использования proc, вы можете использовать блок кода вместо этого. Есть несколько вариантов этого. первый является наиболее очевидным, всего лишь eval
.
set strategy {
puts $x
}
set x "Hello"
eval $strategy
unset x
Это работает, но есть несколько недостатков. Во-первых, очевидно, что оба фрагмента кода должны сговориться об использовании общего имени для аргументов. Это заменяет одну головную боль в пространстве имен (procs) другим (locals), и это, возможно, фактически хуже.
Менее очевидно, что eval намеренно интерпретирует свой аргумент без компиляции байт-кода. Это связано с тем, что предполагается, что eval будет вызываться с динамически генерируемыми, обычно уникальными аргументами, а компиляция в байт-код будет неэффективной, если байт-код будет использоваться только один раз, относительно просто интерпретировать блок немедленно. Это легче исправить, так вот идиома:
set x "Hello"
if 1 $strategy
unset x
if
, в отличие от eval
, компилируется и кэшировать его блок кода.Если блок $strategy
- это только один или только несколько различных возможных значений, то это работает очень хорошо.
Это не помогает с яростью передачи аргументов блоку с локальными переменными. Есть много способов обойти это, например, делать substitutions тем же способом, что и 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 имеет true anonymous functions, используя команду apply
. Первым словом команды apply будет список аргументов и тела, как если бы эти аргументы proc
были отменены. Остальные аргументы передаются в анонимную команду как аргументы немедленно.
set strategy [list {x} {
puts $x
}]
apply $strategy "Hello"
+1 для Tcl 8.5 информация – 2009-07-25 04:59:01
% set val 4444
4444
% set pointer val
val
% eval puts $$pointer
4444
% puts [ set $pointer ]
4444
% set tmp [ set $pointer ]
4444
- 1. Есть ли у turing машины понятие «время»?
- 2. Есть ли у Couchbase понятие «обязательное поле»?
- 3. Есть ли у Drools Fusion понятие «сейчас»?
- 4. Есть ли у JavaScript понятие l-значение и значение r?
- 5. Наследование функций указателей функций
- 6. У встроенных функций есть адреса?
- 7. Есть ли альтернативный синтаксис для указателей функций typedef?
- 8. Есть ли способ хранить различные типы указателей функций в контейнере
- 9. Есть ли у Скалы охранники?
- 10. Перегрузка функций в TCL
- 11. TCL: проверьте, есть ли переменная
- 12. У постоянных указателей есть число суффиксов
- 13. длина массива указателей функций
- 14. Вызов функций C# от Tcl
- 15. Typedef контейнер указателей функций
- 16. Использование указателей функций?
- 17. Обобщение указателей функций
- 18. Безопасно ли вызывать функции указателей функций?
- 19. Обработка функций и указателей
- 20. Есть ли у VB6 способ указания псевдонимов функций?
- 21. Есть ли у python магические методы для всех встроенных функций?
- 22. Объяснение указателей функций
- 23. Назначение указателей функций устройства в CUDA (от указателей функций хоста)
- 24. Правильное использование указателей функций
- 25. У меня проблемы с массивами указателей функций в C
- 26. Определение указателей функций
- 27. Есть ли указатели функций в C#?
- 28. Понимание указателей функций
- 29. Определение указателей функций
- 30. Массив указателей функций C++
Не просите указатели на функцию в TCL, если вы вопрос о реализации Плана стратегии. – JesperE 2008-10-31 13:24:31