Для более близкого знакомства рекомендую эти документы:
Programming in Lua, автор — Roberto Ierusalimschy, один из создателей языка.
Рекомендуется второе издание (на сайте бесплатно выложено первое, частично есть и русский перевод: web, chm).
Справочное руководство по языку Lua 5.1: manual (на русском: web, chm).
local function substr(str, index, length)
if index == nil then index = 1 end
if length == nil then
return str:sub(index)
else
return str:sub(index, index + length - 1)
end
end
local function charAt(str, index)
if index == nil then index = 1 end
return str:sub(index, index)
end
local function charCodeAt(str, index)
if index == nil then index = 1 end
return str:byte(index, index)
end
Хочется их вынести в modules/stringutil.lua и подключать его из макросов, где нужно
Вопросы:
1) Если просто убрать local, и подключать модуль require "stringutil" - ф-ции становятся доступными и работают.
Красиво ли так поступать, или есть какая-то другая общепринятая практика? При проверке luacheck-ом он выдаёт warnings: setting non-standard global variable "substr" и остальные.
2) В идеале хочется, чтоб при подключении require "stringutil" эти ф-ции появлялись в string, и можно было писать str:substr(...).
Попробовал добавить string.substr = substr в конце stringutil.lua - ошибок нет, но при попытке задействовать str:substr(...) ругается на substr - nil value. Как бы это оформить?
Ликбез по Lua
Posted: Thu 10 Nov, 2016 15:08
by Shmuel
1. Общепринятая практика - возвращать в таблице, например return { substr=substr; charAt=charAt }
2. unicode.utf8.substr = substr
Ликбез по Lua
Posted: Thu 10 Nov, 2016 15:53
by John Doe
gene.pavlovsky wrote: эти ф-ции появлялись в string, и можно было писать str:substr(...).
При обмене скриптами рано или поздно возникнет ситуация, когда этих функций у конечного пользователя не окажется, а вы этого и не заметите, ведь при таком использовании не требуется require в каждом скрипте.
Вообще, глядя на приведённые функции, кажется что их лучше заменить идиомами lua.
substr: str:sub(index or 1,length and ((index or 1)+ length-1) or -1 или
local a = index or 1
local b = length and (a + length -1) or -1
str:sub(a,b)
charAt: str:sub(index or 1, index or 1)
charCodeAt: str:byte(index) или charAt(index):byte()
Ликбез по Lua
Posted: Thu 10 Nov, 2016 17:33
by gene.pavlovsky
Shmuel, благодарю, оба варианта работают.
John Doe, lua и его идиомы меня скорее не радуют, чем радуют. Если индекс вычисляется как сложное выражение, его приходится или дублировать, или пихать в зачастую далее ненужную переменную - некрасиво, особенно когда привык к наличию в string-е большого кол-ва удобных ф-ций. Если я свои скрипты буду выкладывать, я постараюсь включить тела свои require в шапку скрипта, или дать ссылку, если это сторонние модули.
Ликбез по Lua
Posted: Thu 10 Nov, 2016 18:57
by John Doe
gene.pavlovsky wrote: Если я свои скрипты буду выкладывать, я постараюсь включить тела свои require в шапку скрипта
Всё равно не очень хорошая практика: нестандартные функции в стандартных библиотеках.
Кто-то иначе захочит определить например, будет конфликт.
Ликбез по Lua
Posted: Thu 10 Nov, 2016 20:44
by Smitis
local ограничивает действие блоком/файлом. Без local - если есть глобальная переменная, используется она. Иначе - локальная.
Для модулей принято возвращать результаты в виде таблицы return {substr=substr,charAt=charAt,charCodeAt=charCodeAt}
Можно создать _macroinit.lua и там прописать типа _G.substr = function(str, index, length) что-то end функция будет глобальной без всяких модулей. Но метод годится только для локального (личного) использования.
Ликбез по Lua
Posted: Thu 10 Nov, 2016 20:57
by Smitis
gene.pavlovsky wrote:Если индекс вычисляется как сложное выражение, его приходится или дублировать, или пихать в зачастую далее ненужную переменную - некрасиво, особенно когда привык к наличию в string-е большого кол-ва удобных ф-ций.
Что-то не осилил, сорри. Если результат выражения нужен более одного раза, как можно обойтись без промежуточного сохранения результатов? А переменные можно использовать local.
Ликбез по Lua
Posted: Thu 10 Nov, 2016 21:35
by John Doe
Smitis wrote: Если результат выражения нужен более одного раза, как можно обойтись без промежуточного сохранения результатов?
Имелось ввиду функцию определить, в которой эта кухня будет скрыта.
Ликбез по Lua
Posted: Thu 10 Nov, 2016 23:38
by gene.pavlovsky
John Doe Согласен, что для обмена кодом практика не очень хорошая. Но надо же как-то с этим lua выживать... Smitis str:sub(startIndex + anotherStr:len() + 2, startIndex + anotherStr:len() + 4) или str:substr(startIndex + anotherStr:len() + 2, 3) - имел в виду вот это.
local t = {}
setmetatable(t,{
__len = function(self) return 3 end, --Размер этого "массива" теперь всегда 3
})
for i = 1, 8 do table.insert(t, i) end -- В массиве теперь 8 элементов,
far.Show(#t) -- но результат всё равно должен быть 3
выдаёт вместо трёх - восемь. А если заменить функцию на
__len = function(self) error"__len!!!" end, --Размер этого "массива" теперь не узнать
то error не срабатывает. В общем, такое впечатление, что часть метаметодов не заменяются на пользовательские обработчики. Хотя Lua о них знает: в lua51.dll содержится строка __index__newindex__gc__mode__eq__len__lt__le__concat__call__add__sub__mul__div__mod__pow__unm__metatable__tostring__new__pairs__ipairs.