Antontsue
вот это крашится
Antontsue
Quest = Class('Quest', EventListener)
function Quest:init(body)
local o = self.Super()
o.condition = nil
o.body = body
o.co = coroutine.create(o.body)
return self.Inst(o)
end
Antontsue
тоесть если мембер вариабл вызывать то краш
Antontsue
[string "Scripts/Quests/questLogic.lua"]:38: attempt to call a nil value (field 'condition')
Antontsue
делаю так:
function Quest:interrupt(condition)
print('condition', condition)
self.condition = condition
coroutine.yield()
end
-- вызываю так:
local condition
condition = function (a)
print('coroutine condition print')
return 'success'
end
print('coroutine condition', condition)
quest.interrupt(condition)
выводит:
coroutine condition function: 0x218df60
condition nil
Antontsue
она получается не передается в функцию
Antontsue
как такое возможно
Antontsue
https://www.lua.org/cgi-bin/demo
Antontsue
тут тоже самое выдает
Antontsue
о нашел - двоеточие надо было поставить
Antontsue
йоу а как делать множественное наследлвание?
Antontsue
или вы юзаете дак-тайпинг?
Snusmumriken
Множественное наследование - это вместо таблицы в __index - функция, которая перебирает ключи классов. И это медленно и стрёмно. Даже не думай никогда о множественном наследовании.
Snusmumriken
Заменим "сигу" на "множественное наследование".
Snusmumriken
Проще уж миксины, делаются аналогично: в __index - функция, перебирающая миксины и один наследуемый класс.
Миксины - маленькие таблички с небольшим набором методов. Я могу такое сделать, но всё равно будут большие косяки со многими вещами. Особенно с отладкой.
Roman
Хм, и чем тогда "множественное наследование" отличается от миксинов? Вовсе и не стремно, функцию __index специально придумали, чтобы всякие javascript'ы завидовали
Tverd
Множественно наследование может иметь множество инициализаторов... которые надо проходить в момент создания объекта... Миксины обычно без инициализаторов
Antontsue
хорошо, а если вариант с одним предком и множеством интерфейсов?
Antontsue
надо указать что объект реализует какие-то функции, ну например есть интерфейс EventListener, у него есть метод OnEvent(). есть EventDispatcher с методом addListener, в который передается инстанс EventListener-а - так как мваров там не надо, до хватит и формальной реализации протокола - EventDispatcher будет вызывать метод OnEvent()
Tverd
Ну вот миксины считай что-то типа интерфейсов
Antontsue
а приведи пример
Antontsue
вот есть MyObject = Class()
Antontsue
...
Antontsue
как указать что он реализует интерфейс EventListener?
Tverd
MyChild = Class(MyObject, EventListener, Mutota, Fignya)
Tverd
но это придется скорее всего писать самому класс
Antontsue
у Class всего 2 параметра
Antontsue
я так понял что я прсото могу написать MyObject:OnEvent безо всяких формальных указаний и это будет рабатть, но как такой код читать то?
Tverd
это у твоего )
Snusmumriken
Хех, товарищи, вы переусложняете.
Antontsue
ну упрости
Antontsue
Snusmumriken
Примерно такие миксины. Только миксины должны быть максимально простыми.
Snusmumriken
Snusmumriken
Не требующими инициализации и цепляющимися за минимум параметров объекта, чтобы было легко проверять.
И не трогающими любые другие методы объекта, кроме своих.
В идеале - при инициализации объекта, миксин должен проверять наличие всех своих переменных.
Snusmumriken
И тем не менее, это рак убивающий, требующий минимума использования :3
Ибо код с одной стороны гораздо легче превращается в кашу, а с другой - если одни миксины используют те же имена методов что и другие - приходится десять раз проверять приоритеты. Или именовать методы миксинов, включая имя миксина, вроде: obj:posGetPosition и obj:sizeGetSize(), где первый "префикс" - по имени миксина.
И нужен прямой доступ к миксинам типа: self.Super[mixinname].method(self, ...), то есть, миксины ещё стоит именовать.
Oleg
Ребята, посоветуйте решение.
Есть файл, содержащий комбинации клавиш, описание и действие, типа:
a a a
this is aaa
say "aaa"
a b c
this is abc
say "abc"
Нужен код, который перегонит это в массив, типа:
keys[a][a][a][description] = "this is aaa"
keys[a][a][a][action] = 'say "aaa"'
keys[a][b][c][description] = "this is abc"
keys[a][b][c][action] = 'say "abc"'
Oleg
Через load()() делать?
Snusmumriken
1. Если у тебя есть выбор в чём хранить - используй json. Он крайне универсален и избавляет от моря проблем.
2. Если нет выбора - пишешь парсер типа такого:
function load(path)
local file = io.open(path)
loca raw_data = file:read('*all'); file:close()
local raw_blocks = {}
for line in (raw_data..'\n\n'):gmatch('(.-)\n\n') do
table.insert(raw_blocks. line)
end
local keys = {}
for i, v in ipairs(raw_blocks) do
local a, b, c = v:match('(%w) (%w) (%w)')
keys[a] = keys[a] or {}
keys[a][b] = keys[a][b] or {}
keys[a][b][c] = keys[a][b][c] or {}
local desc, act = v:match('\n(.-)\n(.*)')
keys[a][b][c].description = desc
keys[a][b][c].action = act
end
return keys
end
Snusmumriken
Я не проверял, тут могут быть мелкие баги, но суть думаю ясна. Ещё стоит вычистить лишние пробелы, если в изначальном файле перед фразой есть лишние пробелы.
Распустил на много строк чтобы читать было удобнее.
Tverd
я храню в луа скриптах, если менять не надо ничего\
Tverd
это намного проще )
Snusmumriken
Ну как тебе сказать. Есть очень много очень классных сериализаторов.
Например, serpent. Он корректно сериализует в lua-табличку в том числе функции, например.
Им можно полноценно сериализовать объекты.
Snusmumriken
Но конфигурационные файлы всё же стоит хранить в json.
Так же как пересылаемые сообщения - тоже он же.
Количество ёбли уменьшается во много раз, даже по сравнению с XML.
Snusmumriken
Меня сильно удивляет то, что всякие html до сих пор не перевели на что-то json-подобное, потому что читаемость может вырасти на порядок.
Хоть и за DOM-структурой придётся следить строже.
Oleg
А если комбинация ключей в строке произвольной длины и заранее неизвестна?
Oleg
то есть может быть
a a a
а может
a a b d a q
Snusmumriken
Тогда пиши усложнённый парсер, который сплитит первую строку полностью :3
Oleg
Это как?
Oleg
Мне на ум пришло только раскукожить строчку и пихнуть в load.
Oleg
Понимаю что в джейсоне оно правильней, но не хочу. Там нужно следить за скобками и прочей хренью. А тут у меня такая топорная, но простая и понятная форма.
Oleg
То есть мне надо этот конфиг будет часто руками править и в поле action там будет луа-код для исполнения. Если в джейсоне, его же надо будет экранировать?
Snusmumriken
Так же как делим на блоки.
v = raw_block[i]
local letters = {}
for letter in ((v:match('(.-)\n')):gsub(' ', ''):gmatch('%w') do
table.insert(letters, letter)
end
Snusmumriken
Ну, match - выделяет первую строку,
gsub - заменяет пробелы на пустоты,
gmatch - проходит по каждой букве.
Прежде чем писать что-то своё, тебе придётся учить регулярки.
Потом - пробиваем путь в табличке по буквам циклом.
local t = keys[i] or {}
for i, v in ipairs(letters) do
t[v] = t[v] or {}
t = t[v]
end
t.description, t.action = ....
Tverd
проще тогда DSL шлепнуть
Tverd
хотя не, не сильно проще, но полезнее )
Oleg
Что значит dsl шлёпнуть? Если что, я чайник =)
Tverd
написать в смысле )
Snusmumriken
Карочи, товарищ, давай по человечески, а json ты можешь и автоматически сгенерировать : 3
Tverd
ну да, согласен, на данный момент лучше всего json завести
Oleg
А что в итоге получается в t?
Oleg
Не догоняю.
Snusmumriken
Пробиваем ключ. А под конец, в t вгоняем description и action
Oleg
Мой конфиг больше похож на yaml, чем json. Только нужное, без лишней херни.
Oleg
Тем более достаточно прост. Вот отсюда и такая задача.
Snusmumriken
Вот и используй yaml.
https://github.com/gvvaughan/lyaml
Snusmumriken
Кстати, многомерный массив тебе не нужен.
Достаточно key-value:
abcd
desc = ...
act = ...
Который превращается в табличку:
{
abcd = {desc = ..., act = ...}
}
Alexander
Alexander
а если всякие там ctrl и другие названия клавиш не в один символ, то так и храним с пробелами
"a b ctrl d"
Snusmumriken
Есть такое искусство - искусство упрощать.
Причём не только формат передачи, но и свою работу.
Ты, вон, можешь сделать ещё проще, и сделать свой язык программирования, который воспринимает естественный текст:
"Сделай мне массив А из двадцати значений, заполненный нулями, но чтобы каждое пятое значение было единицей, а шестое - двойкой"
и "Разверни, пожалуйста, только что созданный сервер на восьмидесятом порте".
Но ты представляешь, с какими трудностями ты столкнёшься, ваяя интерпретатор?
Прежде чем изобретать велосипед - пользуйся тем что люди уже сделали. И велосипедь только в крайнем случае, когда что-то тебе ну совсем уж не подходит.
Alexander
*me мерзко хихикает, вспомнив байку про робота, которому дали задание выбросить глобусы
Snusmumriken
Хех, естественные языки ещё и двусмысленны :3
Придётся учитывать и это тоже.
Alexander
байку знаешь? :)
Snusmumriken
Не а, давай, рассказывай.
Alexander
Джон купил домашнего робота. Первым заданием для него было - почистить кремом ботинки.
На вопрос робота, что такое крем, человек ответил "густая однородная масса светло-коричневого цвета".
Когда Джон вернулся, оказалось что робот намазал на ботинки яблочный джем.
Джон рассердился, но робот резонно заметил, что джем полностью подходит под описание.
Вторым заданием для робота было выбросить из комнаты старые глобусы.
Глобус Джон описал как "шарообразный предмет на тонкой ножке".
Тогда робот схватил Джона за голову и выбросил его из комнаты, сломав при этом шею.
Snusmumriken
Оу е!
Snusmumriken
Не, на естественном языке вполне можно писать программы: вон, люди же как-то общаются друг между другом, и ничего. Инструктировать друг друга могут.
Просто нужно будет запихнуть весь человеческий языковой опыт в формальный, машиночитаемый вид :3
Alexander
зато сколько недоразумений бывает :)
Snusmumriken
Ну, значит что-то надо описать подробнее, и качество программиста будет измеряться в способности чётко излагать свои мысли.
Обычно, кстати, у программистов с этим проблемы :3
B
я видимо сильно устал но как получить остатком от деления числа само число?