Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #71, ОКТЯБРЬ 2006 г.

дублер каскадера

АЛЕКСАНДР ГЛАДЫШ

Спецвыпуск: Хакер, номер #071, стр. 071-068-7


[2] = { type_ = “button”; name_ = ”settings”; };

[3] = { type_ = “button”; name_ = ”exit”; };

};

};

[2] = { type_ = “panel”; name_ = “settings”; … };

};

};

[«самозагружающиеся» данные.]

Уже в описанном виде с данными можно эффективно работать. Однако это не всегда удобно – если сохраненные данные соответствовали каким-то «живым» объектам логики приложения, придется писать отдельный код по созданию и настройке этих объектов на основе получившихся таблиц. Было бы удобнее создавать объекты сразу же. Это вполне возможно. Один из путей – встроить код создания объектов логики в функции-модификаторы, возвращаемые дочерними ключами, и изменить логику обхода потомков. Если потомку нужна информация о предке, нужно делать обход потомков не сразу при вызове функции – ключевого слова, как сделано выше, - а начиная с корневого элемента. При этом нужно дополнительно передавать модификаторам данные о предке.

Пример для случая, когда для создания нашего элемента пользовательского интерфейса нужна информация о родительском окне:

panel= name_data(“panel”) function(name, data)

return function(data, parent_wnd)

local wnd = Window.Create(name, parent_wnd)

process_child_keywords(data, wnd)

end

end)

Подразумевается, что функция process_child_keywords была модифицирована, чтобы передавать вместе с данными предка еще один параметр – его окно. Нужно модифицировать и реализацию ключевых слов без параметров. При таком подходе они должны уметь изменять свойства самого окна – изменять данные уже поздно. Например, для hidden:

hidden = function(data, wnd) wnd:SetVisible(false) end

Если параметр, изменяемый ключевым словом без аргумента, должен быть доступен на этапе до того, как возможна обработка всех потомков (например, если в приведенном примере нужно передать модальность окна в Window.Create), необходимо реализовать тем или иным способом обход потомков в два прохода. Самый простой способ – вложить функцию-модификатор параметризованного ключевого слова в еще одну такую же и вызывать process_child_keywords дважды (такую реализацию можно абстрагировать подобно name_data):

panel= name_data(“panel”) function(name, data)

return function(data)

return function(data, parent_wnd)

process_child_keywords(data) – Data modifiers

local wnd = Window.Create(name, parent_wnd, data.modal)

process_child_keywords(data, wnd) -- Child windows

end

end

end)

[кодогенерация.]

Видно, что с увеличением сложности структуры данных усложняется и реализация ключевых слов, и сопутствующего им кода. Растут накладные расходы по производительности загрузки данных. В последнем примере требуется, как минимум, пять вложенных вызовов функций, прежде чем дело доходит до непосредственного создания объекта. В действительности это не очень страшно – виртуальная машина Lua обладает очень высокой производительностью и, к тому же, поддерживает «хвостовые» вызовы функций (tail function calls) (в частности, хвостовую рекурсию tail recursion), что позволяет эффективно оптимизировать вызовы вида return functioncall и снимает ограничение на количество вложенных вызовов функций такого рода.

Назад на стр. 071-068-6  Содержание  Вперед на стр. 071-068-8