В какой момент должны быть созданы обработчики callback-ов, чтобы они вызывались? Экспериментально, если создавать некоторые функции обработчиков (например, main) внутри OnInit, то они работают, некоторые (например, OnQuote) - не работают. Возможно, адрес каких-то обработчикаов кешируется в какой-то момент и его последующие изменения в адресах функцииLua не учитываются?
s_mike@rambler.ru написал: К сожалению, связывание обработчиков идет в момент запуска скрипта и создание обработчика в процессе работы скрипта уже ни к чему не приводит.
На мой взгляд это недоработка и связывание должно быть динамическим, но "начальник всегда прав" (((
В этом есть резон, например, чтобы не обращаться при каждом OnQuote в Lua за текущим адресом обработчика. Однако, часть работает так, часть - по-другому, логики не прослеживается. Если это из соображений скорости, то хорошим выходом было бы создание API, типа UpdateCallbackHandlers, которую скриптер мог бы вызывать эксплицитно, если что-то поменял.
Сделать стандартный обработчик с вызовам вашей "потом сгенерированной" функции - вот и решение. Любопытно, кстати: зачем генерировать обработчики в run-time?
swerg написал: Любопытно, кстати: зачем генерировать обработчики в run-time?
Один из случаев, который был бы удобен многим, чтобы упрощать слежение корректности стейта. Сейчас, например, если есть поведение, зависящее от стейта, то нужно в каждом коллбеке делать проверки на то, от чего он зависит. Если бы можно было переназначать обработчики, то вся вариативность бы укладывалась бы в одом if-е в каком-нибудь OnInit, где инициализируются и переменные, и функции обратного вызова. Таким образом, можно было бы добиться инкапсуляции данных и поведения "для бедных" в Lua.
все колбеки у меня описаны в теле основного макроса. затем, если мне надо без перезпуска этого макроса изменить текст какой-то процедуры, я по нажатию на определенную кнопку, запускаю командой dofile внешний файл lua, в котором в свою очередь идет вызов: dofile (getScriptPath().."\\. .\\хххххххх.lua") где хххххххх имя основного файла. Таким образом он его снова перекомпилирует, и если его текст был изменен, то все функции начинают работать "по-новому". У меня все перекрасно работает. можете попробовать
Sergey Denegin написал: я пользуюсь такой штукой: ... Таким образом он его снова перекомпилирует, и если его текст был изменен, то все функции начинают работать "по-новому". У меня все перекрасно работает. можете попробовать
У меня сама проблема решена (в С++), я скорее хотел прояснить, как же оно на самом деле задумано, с учетом того, что некоторые колбеки успешно переопределяются. В документации ничего про то, когда их можно определять, я не нашел.
swerg написал: Любопытно, кстати: зачем генерировать обработчики в run-time?
Один из случаев, который был бы удобен многим, чтобы упрощать слежение корректности стейта. Сейчас, например, если есть поведение, зависящее от стейта, то нужно в каждом коллбеке делать проверки на то, от чего он зависит. Если бы можно было переназначать обработчики, то вся вариативность бы укладывалась бы в одом if-е в каком-нибудь OnInit, где инициализируются и переменные, и функции обратного вызова. Таким образом, можно было бы добиться инкапсуляции данных и поведения "для бедных" в Lua.
swerg написал: Любопытно, кстати: зачем генерировать обработчики в run-time?
Один из случаев, который был бы удобен многим, чтобы упрощать слежение корректности стейта. Сейчас, например, если есть поведение, зависящее от стейта, то нужно в каждом коллбеке делать проверки на то, от чего он зависит. Если бы можно было переназначать обработчики, то вся вариативность бы укладывалась бы в одом if-е в каком-нибудь OnInit, где инициализируются и переменные, и функции обратного вызова. Таким образом, можно было бы добиться инкапсуляции данных и поведения "для бедных" в Lua.
можно как-то на примере?
Было бы:
Код
Инициализация_скрипта:
x = внешние_данные
if (x == A)
дополнительная манипуляция над данными
if (x.z == 1)
манипуляция_состоянием1...
OnAllTr ade = My_OnAllTrade1
OnQu ote = My_OnQuote1
...
if (x.z == 2)
манипуляция_состоянием2...
OnAllTr ade = My_OnAllTrade1
OnQu ote = My_OnQuote2
...
if (x.z == 3)
манипуляция_состоянием3
OnAllTr ade = My_OnAllTrade1
OnQu ote = My_OnQuote2
...
else ...
Это эквивалентно динамическому полиморфизму в ООП языках.
Сейчас пришлось бы делать так:
Код
Инициализация_скрипта:
x = внешние_данные
OnQuote:
if (x == A)
манипуляция над частью данных
if (x.z == 1)
OnAllTr ade = My_OnAllTrade1
OnQu ote = My_OnQuote1
...
if (x.z == 2)
...
if (x.z == 3)
OnAllTrade:
разбор для всех тех же случаев
В итоге получается, что вся вариативность поведения разбросана внутри каждого коллбека и нужно раздублировать все проверки на состояние внутри. Чуть более сложный сценарий, в зависимости от состояния переназначать коллбеки, например, чтоб не вызывался один OnAllTrade, пока не сработал другой колбек (сейчас альтернатива, опять же, засунуть все в один OnAllTrade и делать там разбор случаев). Вобщем-то даже в Lua при всей ее примитивности заложена философия first-class функций, и такая работа с функциями, как динамическое переназначение на имя другой лямбды, вполне в ее духе.
swerg написал: Любопытно, кстати: зачем генерировать обработчики в run-time?
Один из случаев, который был бы удобен многим, чтобы упрощать слежение корректности стейта. Сейчас, например, если есть поведение, зависящее от стейта, то нужно в каждом коллбеке делать проверки на то, от чего он зависит. Если бы можно было переназначать обработчики, то вся вариативность бы укладывалась бы в одом if-е в каком-нибудь OnInit, где инициализируются и переменные, и функции обратного вызова. Таким образом, можно было бы добиться инкапсуляции данных и поведения "для бедных" в Lua.
Это эквивалентно динамическому полиморфизму в ООП языках.
Сейчас пришлось бы делать так:
Код
Инициализация_скрипта:
x = внешние_данные
OnQuote:
if (x = = A)
манипуляция над частью данных
if (x.z = = 1 )
OnAllTr ade = My_OnAllTrade1
OnQu ote = My_OnQuote1
.. .
if (x.z = = 2 )
.. .
if (x.z = = 3 )
OnAllTrade:
разбор для всех тех же случаев
В итоге получается, что вся вариативность поведения разбросана внутри каждого коллбека и нужно раздублировать все проверки на состояние внутри. Чуть более сложный сценарий, в зависимости от состояния переназначать коллбеки, например, чтоб не вызывался один OnAllTrade, пока не сработал другой колбек (сейчас альтернатива, опять же, засунуть все в один OnAllTrade и делать там разбор случаев). Вобщем-то даже в Lua при всей ее примитивности заложена философия first-class функций, и такая работа с функциями, как динамическое переназначение на имя другой лямбды, вполне в ее духе.
Как варианты: 1)Можно вынести разбор состояний в функцию 2) Можно ввести глобальный флаг и не разбирать снова если это тоже самое.
Есть еще одно решение. Lua позволяет запускать функции с помощью вызова _G
Т.е. если в вашем примере есть три функции My_OnAllTrade1, My_OnAllTrade2, My_OnAllTrade3 То в обычном OnQuote делается такой вызов: _G["My_OnAllTrade"..x.z]
Вуаля! в зависимости от значения переменной x.z он будет вызывать разные функции. Я так делаю, все работает.