LINUX.ORG.RU

составной оператор есть в tcl?

 


1

2

Не рекомендуется составлять скрипты для биндингов из строк. Говорят, делай

[list ::nsp::myproc $arg1 $arg2]
А мне нужно привязать биндинг, который сначала что-то вызывает, а потом возвращает break. Как поступить? Если я вставлю в список точку с запятой, ничего не выйдет же.

★★★★★

Последнее исправление: den73 (всего исправлений: 1)
proc @ {args} {
  list ::tcl::apply [ lrange $args 0 1 ] {*}[ lrange $args 2 end ]
}
bind . <<MyEvent>> [ @ {x y} { foo $x $y ; return -code break } $arg1 $arg2 ]
MKuznetsov ★★★★★
()
Ответ на: комментарий от den73

Или это православная строка?

Tcl православен - там всё строка :-)

ps. «Не рекомендуется составлять скрипты для биндингов из строк» - это чтобы не попадать лишний раз в quoting hell и работал байт-компилер

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

Ну а как же мне (начинающему) отличить «лишнее» попадание в quoting hell от «заслуженного»? Пытаюсь использовать только безопасные варианты. Тут вроде в твоём коде придраться не к чему, хотя, честно сказать, я не могу сказать, что на 100% уложил в голове правила «квотинга». Ну и байт-компилятор - тоже цель достойная.

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73
label .t  -text "Hello"
set message "Hello"
bind .t <Enter> [concat puts $message ";" exit]

Нет?

buddhist ★★★★★
()
Ответ на: комментарий от MKuznetsov
proc @ {args} {
  list ::tcl::apply [ lrange $args 0 1 ] {*}[ lrange $args 2 end ]
}
bind . <<MyEvent>> [ @ {x y} { foo $x $y ; return -code break } $arg1 $arg2 ]

В общем, я правильно понял, что напрямую составного оператора нет?

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

Tcl

оператора

Нет, ты все неправильно понял :)

buddhist ★★★★★
()
Ответ на: комментарий от MKuznetsov

Нет, ты все неправильно понял :)

Ну, не прямо уж «всё».

Твой код у меня в таком виде более-менее заработал

# Так нормально
set cmd [concat [list tk_messageBox -message "hello"] ";" break]
# А если это раскомментарить, то проскочит и в следующий обработчик
# set cmd [concat [list tk_messageBox -message "hello"]]

text .t 
.t insert 1.0 $cmd
pack .t
bind . <F3> "tk_messageBox -message {:(}"

bind .t <F3> $cmd

den73 ★★★★★
() автор топика
Ответ на: комментарий от MKuznetsov

отличить «лишнее» попадание в quoting hell

не обрамлять код кавычками "".

Ладно, в общем, ясно, что ничего не ясно. Во всяком случае, свою локальную задачу я почему-то решил. Нужная мне функция сама уже возвращает -code break. Эксперимент показал, что всё сработало правильно, хотя у меня нет уверенности, что я правильно понял, как оно работает. Едем дальше :)

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

Еще можно так:

bind .w <<Event>> [list procedure $arg1 $arg2]
bind .w <<Event>> +break
В этом случае второй биндинг не перекроет первый, а к нему добавится.

TeopeTuK ★★★★★
()
Ответ на: комментарий от TeopeTuK

Для этого решения нужно осилить доку по команде bind, на это пока нет сил. Иначе не вижу гарантии, почему break сработает после, а не до [list procedure ... ] Мне больше всего нравится вариант, предложенный buddhist-ом и доработанный мной.

den73 ★★★★★
() автор топика
Ответ на: комментарий от buddhist

А здесь откуда должен быть брейк?

Стороны перестали друг друга понимать :) Уточни, что такое «здесь».

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

Я соглашусь, что придумать что-то самостоятельно интереснее, чем читать документацию. Но скорее всего и времени отнимет больше. Плюсик перед скриптом именно что добавляет скрипт в конец к уже привязанным, так что сработать «до» у него мало шансов.

TeopeTuK ★★★★★
()
Ответ на: комментарий от TeopeTuK

Тут есть и другие минусы. Например, не очень красив вот такой повтор:

bind SingleMod$w <Control-Key-F12> $cmd
bind SingleMod$w <Control-Key-F12> +break

А также знание о том, что биндинг всегда не более чем один, помогает в анализе. Если этого знания нет, анализировать сложнее.

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

Может покажусь Капитаном, но в строке:

 set cmd [concat [list tk_messageBox -message "hello"] ";" break] 
вообще не нужно динамически формировать строку. Тут обычный статичный код, не содержащий переменных или вложенных команд, поэтому его можно сразу же записать в фигурных скобках. Пример:
 set cmd  {tk_messageBox -message "hello" ; break} 

anonymous
()
Ответ на: комментарий от anonymous

Вообще там, как правило, бывает имя окна. Но я просто в целом пытаюсь понять, как обходиться со сгенерированным кодом, поскольку вариант «сгенерируй замыкание и выполни его после ответа с сервера» - постоянно встречающаяся ситуация. Вот и думаю, можно ли тут list-ом обойтись.

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

Красота — понятие субъективное. Не нравится, не делай. Что же касается «более, чем одного биндинга», то так не бывает. Одному событию для одного тега может соответствовать не более одного биндинга:

% wish
% bind . <<SomeEvent>> script
% bind . <<SomeEvent>> +break
% bind . <<SomeEvent>>
script
break
%
Выведенные две строки это один двустрочный скрипт. А break нужен для того, чтобы скрипты, прибинденные к другим тегам для того же события, не выполнялись (я убежден, что ты это и так знаешь, но вдруг еще кто-нибудь прочитает):
% bindtags .
. Wish all
%

TeopeTuK ★★★★★
()
Ответ на: комментарий от TeopeTuK

Ну что, ты достойно защитил свою точку зрения.

То, что ты предлагаешь, является допустимым решением. Но биндинги - это частность. Я в целом не понимаю, как правильно генерить замыкания в tcl и пока к пониманию не особо приблизился, хотя в моём приложении опробовал несколько вариантов. После лиспа все они выглядят лагерной баландой, кроме самого красивого, который, как я понял, ведёт в кавычечный ад. Вот такого:

::tkcon::EvalInSwankAsync $lispCmd [subst -nocommands {
 ::ldbg::InsertLocsNTagsForFrameIntoTree $RowName \$EventAsList
 }] [GetDebuggerThreadId]

Здесь генерируемый код визуально похож именно на код и не нужны эти ужасные обратные кавычки в конце строки. Был, правда, ещё вариант с лямбдами, но там ЕМНИП не получалось сделать, чтобы выглядело как код и при этом чтобы это было замыкание, т.е. чтобы часть подстановок сделать в момент генерации кода.

Поэтому мой конкретный вопрос про биндинги - это лишь повод для более общего вопроса. Вариант с +break - в этом плане не общий и не является ответом на основной вопрос.

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

Вот я кстати наутро проснулся и понял, что от кавычечного ада в некоторой степени защитит следование правилам:

1. Не допускать значений по умолчанию для аргументов функции. Именованные аргументы должны быть отдельным обязательным аргументом - списком.

2. Избегать передачу пустой строки в качестве «лжи». Использовать вместо этого ноль.

К сожалению, сами команды tcl первое правило мало когда выполняют, имеют множество необязательных ключей, да ещё и следующих в разном порядке. Кроме того, есть риск перепутать ключ и данные. Так что это похоже на недостаток tcl, который никак не обойти.

den73 ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.