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

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


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

С чего начинать и где взять.

 

Установка Lua:
http://www.amk-team.ru/forum/index.php?showtopic=11584&p=629106

 

Руководство «Программирование на языке Lua», третье издание:
http://www.amk-team.ru/forum/index.php?showtopic=11584&p=905308

Изменено пользователем Kirgudu
Ссылка на комментарий

Ну а по "нормальному", т.е. с проверками корректности заданных строк:

prefetch(new_scr) --/ не обязательно, но не помешает ...
if type(_G[new_scr]) == 'table' and  type(_G[new_scr][func_1]) == 'function' then
  _G[new_scr][func_1]() --/ вызов функции
end

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

Artos,

все же вариант Real Wolf более общий и гибкий. Примерно так у меня было сделано в моей реализации сохраняемых таймеров.

local f, msg = loadstring("return "..timer_class.."(...)"
local timer = f()

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

Полный текст приводил в этом посте.

 

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Ссылка на комментарий

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

Ну а что более обще иль гибче - все же опять и от конкретного контекста зависит и от вкусов.

Вариант с _G[file_name][func_name] использован разработчиками в том же xr_logic.script, что дает возможность "вспомнить" тем, кто подзабыл как вызвать функцию.

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

Artos,

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

вариант с _G[<имя модуля>][<имя функции>]

достоинства:

быстрый, годится для частых вызовов

недостатки:

1. Требует парсинга исходной строки для разбиения ее на имя модуля / имя функции.

2. Ограничивает общий вид строки с полным адресом функции. Грубо говоря, количество точек должно быть фиксированное. Более точно, строка должна иметь предсказуемый формат для парсинга.

 

вариант с loadstring

достоинства:

1. Простой. Код для вызова элементарен

2. Нет ограничения на вид строки с именем вызываемой функции. Это даже может быть что-то нетривиальное, лишь бы было кодом Lua.

недостатки:

Затратный с точки зрения времени выполнения. loadstring компилирует вспомогательную функцию, что естественно требует затрат. Во многих случаях это не критично, как в упомянутых таймерах. Там это используется для разового действия создания таймера. Частично недостаток можно скомпенсировать, сохранив вспомогательную функцию.

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Ссылка на комментарий

Согласен с таким резюме.

Может быть добавил бы еще для _G[<имя модуля>]:

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

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

 

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

Как получить текстовое название скрипта, в котором находится функция?

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

Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О

Мастер аномалий на свою заднюю точку.

Ссылка на комментарий

*Shoker*,

В чистом Lua можно только через debug. В сталкере однако есть небольшое расширение на этот счёт.

script_name() - возвращает имя текущего модуля без расширения

Также на всякий случай

this - ссылка на текущий модуль (таблица)

Работает только в файлах с расширением *.script

 

  • Нравится 1
 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Ссылка на комментарий

*Shoker*,

Нужно знать откуда и при каких условиях запрашивается это имя.

А в общем случае так :

имя файла *.sсriрt является модулем, а значит полем глобальной таблицы luа, с ключем - именем модуля (именем файла) и значением - таблица. В этой таблице находятся все глобально объявленные (для данного модуля) поля. И твоя искомая функция тоже (если не объявлена локально).

Вывод. Парси _G на предмет наличия таблиц, в которых есть поле с ключем - именем функции.

 

Ключ найденной таблицы и будет именем файла.

Нюансы пока не трогаем.

Изменено пользователем Gun12
Ссылка на комментарий

Gun12,

два вопроса:

1. Как отличить поля с таблицами-модулями от полей просто таблиц, коих в глобальном пространстве имен предостаточно?

2. Как узнать, что это именно твой текущий модуль?

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Ссылка на комментарий

malandrinus,

Нюансы пока не трогаем.

Нюансы заключаются в том, что хоть в разных модулях и можно создавать поля с одинаковыми именами, но делать этого я бы не стал (без причины).

Уникальное имя будет только одно. И оно будет находиться только в той таблице, которая и будет считанным модулем.

Ссылка на комментарий

Gun12,

все же куча потенциальнфх проблем:

1. Совпадение имен. Во-первых, а чего плохого в том, что в разных модулях есть функции с разными именами? Наличие функций с одинаковыми именами может быть требованием дизайна, к примеру функции с именами типа init, setup, обработчики событий в модулях, связанных с системами сигналов (наподобие систем xStream или моей). Далее, в некой таблице, не являющейся модулем, может оказаться поле с именем, совпадающим с именем текущей функции. Это может вообще получиться непреднамеренно в ходе динамического заполнения таблицы из файла конфига или именами секций объектов или еще каким-то способом, исключающим контроль на стадии написания кода.

2. Функция может быть безымянной

3. Придется поддерживать синхронность между именем функции, которое в общем может измениться в ходе редизайна кода, и этим фрагментом.

 

Если так рассуждать, то я вероятно выберу из двух зол меньшее: просто буду вставлять вручную строчку с именем модуля. Но однако есть script_name(), так что можно не париться.

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Ссылка на комментарий

malandrinus, Gun12

Спасибо, подошёл script_name(), самый удобный способ, и без заморочек.

Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О

Мастер аномалий на свою заднюю точку.

Ссылка на комментарий

malandrinus,

То, что в Сталкере есть готовая функция - это конечно хорошо.

Но не для меня, раз уж мы в теме о lua. Ну нет, скажем, готовой.

Чем не подходит

Парсим _G и сравниваем с this

А говоря языком lua :

Там где нужно парсим _G и сравниваем с _M.

 

Ссылка на комментарий

Gun12,

если нужен чистый Lua, то тогда имеет смысл задействовать debug. Кажется функция debug.getinfo позволяет получать нужную информацию. К примеру, debug.getinfo(1,"n") дает имя текущей функции, но там можно получить гораздо больше информации. Может и имя модуля можно, точно не знаю.

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Ссылка на комментарий

Это известно.

Если нужно, можно поговорить и о чистом luа.

Но всё же делаем с оглядкой на сталкер. Dеbug исключается.

Изменено пользователем Gun12
Ссылка на комментарий

Что-то вы заспорились ...

*Shoker*, задал, как обычно, вопрос с общей формулировкой для довольно локальной своей задачи и стОит ли копья ломать?

Если требуется "изнутри" скрипта (игры) определить имя - лучше script_name() не придумать (чего и *Shoker*'у уже достаточно).

Если же "снаружи", то вариантов три:

1. Смотрим, как сами разработчики передавали имя скрипта как аргумент в ту же функцию _g.debug_log ...

2. Используем debug.getinfo (для SHoC имеется расширитель от RvP), что и сами разрабы использовали: local script_тame = debug.getinfo(2).short_src:gsub('%.script', "")

3. Парсим, как предложил Gun12, глобальную метатаблицу _G и сравниваем поля с искомой функцией.

Каждый выбирает свой путь, исходя из потребностей и возможностей. ИМХО.

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

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

Аrtоs,

да никто тут копья не ломает. Дискутируем, разбираемся, ищем, находим. Хорошо что есть с кем. А то молчат все, как будто всё знают.

Ссылка на комментарий

Gun12,

Если нужно, можно поговорить и о чистом luа.

Но всё же делаем с оглядкой на сталкер. Dеbug исключается.

В сталкере есть готовое решение, в чистом Lua есть debug, да и никто не мешает его расширить по самое нехочу, поскольку Lua встраивается в свою систему в виде исходников.

 

Что касается решения с перебором таблиц. Проблема в его неустойчивости и плохой сопровождаемости. Если объективно взвесить все плюсы и минусы, то получится, что проще в паре мест кода незатейливо вставить строки с именем файла, поставить внятный комментарий в этом месте и потом при случае эти строки обновлять. Можно для контроля соорудить функцию проверки наличия модуля и поставить там ассерты для отлова ситуации, когда имя файла изменилось, а эту строку не поменяли. В итоге, времени на сопровождение или адаптацию кода будет мизерным + код простой и прозрачный. С другой стороны, решение с перебором может в итоге потребовать примерно тех же самых манипуляций да еще и не дает стороцентной гарантии результата. Хотели сделать один раз и забыть, а получили сравнимый геморрой + усложненный код.

 

Мне интересно, в связи с чем потребовалось узнавать имя модуля? У меня самого такая задача тоже возникала, но настолько редко, что я бы не заморачивался на автоматизацию даже при отсутствии штатных стредств.

 

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

Artos,

Что-то вы заспорились ...

так ведь и тема в основном для отвлеченной болтовни =)

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Ссылка на комментарий

Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

Создать аккаунт

Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!

Зарегистрировать новый аккаунт

Войти

Есть аккаунт? Войти.

Войти
  • Недавно просматривали   0 пользователей

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