Перейти к контенту

Язык Lua. Общие вопросы программирования


Malandrinus

Рекомендуемые сообщения

(изменено)
Теоретически, поскольку Lua в составе сталкера сделан в виде динамической библиотеки, то можно пересобрать эту библиотеку из исходников и добавить туда то, чего не хватает.

 

Пытался, не прокатило, но только потому, что я не включил в него luabind.

В принципе, есть вероятность что разработчики движка дописать какое-то API сами, но если нет, то в результате, после подключения luabind, должно работать.

Изменено пользователем Monnoroch

Поделиться этим сообщением


Ссылка на сообщение

То есть разработчики все же не вносили изменений в luabind?

Просто не было возможности посмотреть, собирать буст с луабиндом на моем калькуляторе радости мало, и потом, винду еще ставить... но интересно же.

Поделиться этим сообщением


Ссылка на сообщение

malandrinus, посмотрел твои эвенты - красота! Но только почему ASSERT, зачем такая жестокость? Обычно в такой ситуации бросают исключение, потому на мой взгляд логичнее было бы просто ничего не сделать и как-то сообщить пользователю, что он не совсем прав. А то сразу assert делать слишком сурово.

 

В добавок мне видится ситуация, когда я хочу подписаться на эвент, если еще не подписан, и ничего не делать если подписан.

Замена ассерта на более мягкую обработку ошибки позволит тут избавиться от ветвлений типа

if not obj:is_already_subscribed(slot) then
obj:subscribe(slot)
end

К тому же с ветвлением obj:is_already_subscribed вызывается дважды.

 

Либо добавить signals_mgr:subscribe_silently() :)

Поделиться этим сообщением


Ссылка на сообщение
(изменено)

Andrey07071977, Не надо никаких сообщений в лог. Это сажает производительность. Просто далеко не всегда подпись на эвент дважды является ошибкой в логике программы. Особенно учитывая, что мододелов куча и один может в своем моде подписать на A,B,C, а второй на B,C,D и что теперь, совмещающему всматриваться, размышлять? К тому же раскройка модов при совмещении радикально ломает всяческую инкапсуляцию.

С другой стороны получается, что теперь всегда вместо одной строки подписания придется писать три строки проверки-подписания, а всегда потому, что откуда кто знает на какие эвенты обьект уже подписан? Ну и зачем увеличивать клиентский код в три раза? Поэтому просто надо тихо return false, кому надо, тот проверит, но чаще всего это излишняя информация.

Изменено пользователем Monnoroch

Поделиться этим сообщением


Ссылка на сообщение
(изменено)

malandrinus,

Я имею в виду, что вот мы подписали, затем подписали ещё раз, затем ещё и сделали это неопределённое число раз

Хранить счетчик подписываний, а не подписывать каждый раз.

 

А пример я приводил: вот у меня класс хелпер какой-то. Мне присылают обьект и список эвентов на которые подписать.

Задача - подписать на все. Ну понятно же, что не хочется каждый раз проверять - подписан ли уже, и если нет, то подписывать, хочется же сделать код прозрачней.

Ну вот метод:

function subscribe_all(mgr, slots)
  for _,v in pairs(slots)
    mgr:subscribe(v)
  end
end

 

Допустим код одной схемы вызывает:

helper.subscribe_all(mgr, {s1,s2,s3})

А второй:

helper.subscribe_all(mgr, {s2,s3,s4})

Вон как все красиво. Да, можно всунуть if, но как-то уже не то.

Хотя вот я тут подумал - если просто в сам класс подписывателя инкапсулировать этот subscribe_all с if-ом, то будет все хорошо в плане использования.

 

По поводу этого:

когда этот ассерт будет мешать, ну так и убери его...До тех пор у меня такой функции не будет.

Я думал обо всей системе, как о библиотеке, у которой есть интерфейс а реализация меня волновать не должна.

И конечно пользователь сам может определить subscribe_silent с помощью того же if-а и снаружи библиотеки, но это потенциальное дублирование кода - каждый будет свою версию определять.

 

И потом, тут проблема именно в том, что два разных человека подписывают один и тот же обьект на один и тот же эвент. Ну вот выпал мне этот ассерт - что мне делать? Ставить ту самую явную проверку, вариантов особо других нет. Я же не знаю, всегда ли так получается, что он уже подписан. Это же не мой код. И не ошибка в логике.

 

Ты не пойми неправильно, я не пытаюсь учить ученого, просто мне показался странным подобный дизайн модуля, который потенциально может использоваться кучей народу в куче модификаций :)

 

 

Во, кстати, я еще досмотрел и такой вопрос: почему сигнал встраивается в слот? Можно же было бы сделать как-то так:

obj:subscribe(signal,slot), тогда один слот мог бы быть подпинан на множество сигналов в разное время разным кодом.

Изменено пользователем Monnoroch

Поделиться этим сообщением


Ссылка на сообщение
Andrey07071977, Так ведь нет же, я как раз и пытаюсь протолкнуть идею, что двойные подписки - совершенно нормальное явление. Потому и отлавливать их сомнительный профит, разве только если в конкретных случаях.

Поделиться этим сообщением


Ссылка на сообщение

malandrinus, Ситуация простая: некий мододел захотел на непися повесить поведение при неком скриптовом событии - например при выбросе. А выброс, так как наша система работает вокруг слот-сигнальной модели, генерирует сигнал. Ну что делает мододел - подписывает слот на сигнал.

А теперь другой мододел расщедрился и хочет подписать всех сталкеров на это поведение но не знает что один уже подписан. Вот пожалуйста, двойное подписываени.

Слот при этом бутет выглядеть как-то, например, так:

slt = {signal = "blowout", self = obj, fun = obj.hit}

и так для всех сталкеров.

Ну и что, вот человек отлаживает эти моды вместе и видит: в цикле по всем сталкерам оказывается один уже подписан! Ну хорошо, и что ему делать-то? Искать где подписан и отписывать? Это копошение во внутренней реализации мода - не есть хорошо при любом раскладе. Код должен иметь как можно меньшую связность.

А если разрешить двойное подписание, то все разруливается: второе подписывание элементарно игнорируется, вернее увеличивается счетчик подписываний до двух. А когда кто-то отписывает его, счетчик уменьшается до одного. А потом до нуля - и тут физически происходит отписывание.

А сигнал, сколько бы раз на него слот не подписался, вызывает его, естественно только один раз, зачем ему больше? Хотя тут можно даже параметр сделать, это дело настраивающий: один или несколько.

Поделиться этим сообщением


Ссылка на сообщение
(изменено)

malandrinus,

убрать этот фрагмент и оставить более общий

Предположим общий включается на первый выброс и после выключается, а частный должен работать всю игру.

В добавок, в данном случае три строки не помогут: надо отписать общий случай но сохранить частный. То есть соблюдать вложенность.

Я, может, пытаюсь придумать искусственный случай, но в самом деле, кто знает, как будут использовать возможность подписки? Я любитель общих решений :)

И не любитель лезть руками в чужой код, неблагодарное это занятие, может там на четном количестве ошибок в знаке все держится?

Изменено пользователем Monnoroch

Поделиться этим сообщением


Ссылка на сообщение
(изменено)

malandrinus, кстати об этом, а анонимная функция пойдет для решения проблемы?

навроде:

slt = {fun = function() return f() end}

В смысле так же можно?

 

В общем случае сработает ли такое решение:

function duplicate(f)
  return function(...) return f(...) end
end

ASSERT(f ~= duplicate(f),"?")

Изменено пользователем Monnoroch

Поделиться этим сообщением


Ссылка на сообщение
(изменено)

malandrinus, Ну да, зато у меня можно создавать сколько угодно дубликатов :)

 

Добавлено через 29 мин.:

Кто-нибудь может подсказать, можно ли в lua выражение:

if not a then f() end

заменить на

a or f()

И соответственно:

if a then f() end

заменить на

a and f()

 

Чуть более сложнее, может ли там быть statement:

a and c = 1

или

a or return

?

Изменено пользователем Monnoroch

Поделиться этим сообщением


Ссылка на сообщение
(изменено)

Вот, для любителей выкладываю слот-сигнальную систему v 2.0 собственного приготовления. Она чуть более ООП, чуть менее суровая и чуть более настраиваемая.

http://ifolder.ru/28140737

Ах да, делалась она на основе системы malandrinus, из оригинального кода взято обеспечение корректной работы очередей и каменты, так что не надо удивляться :)

И да, спасибо ему за идею.

 

И таки "a or return" не работает, по крайней мере codepad не понимает, потому там такие штуки везде накомментированы, тоже не надо удивляться...

 

Добавлено через 18 мин.:

Как-то слишком сложно.

Если обобщить твой вариант для произвольной функции получится:

function dublicat(f, ...)
    return f(...)
end

Но это странный вариант. Он не создает новую функцию.

А моя функция принимает функцию и возвращает ее копию. А уже копию я могу приписать к тому же сигналу.

Хотя тут явная проблема в том, что отписать этот слот будет затруднительно - только если закэшировать...

Изменено пользователем Monnoroch

Поделиться этим сообщением


Ссылка на сообщение

xStream, Да, я уже это понял :)

Просто в D есть такая штука, что выражения типа void туда пихать можно, в результате всё expression преобразуется в statement и получаются такие вот красивые ветвления.

Поделиться этим сообщением


Ссылка на сообщение

Вот, добавил собственно то, что хотел: возможность множественных подключений слотов, возможность это запретить, некоторые настройки с этим связанные и вообще привел в порядок код.

http://ifolder.ru/28140737

Поделиться этим сообщением


Ссылка на сообщение

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

malandrinus, теперь если в mon_utils.default_slot поставить unique = true, то получится ровно твоя система, но которую можно использовать более гибко :)

 

http://ifolder.ru/28160609

Поделиться этим сообщением


Ссылка на сообщение
  • Недавно просматривали   0 пользователей

    Ни один зарегистрированный пользователь не просматривает эту страницу.

AMK-Team.ru

×
×
  • Создать...