ShadoWalkeR
Господа, есть интересный вопрос. Я хочу сделать switch в lua на основе таблицы. Сейчас сделано так: local sw_event = { ["eventA"] = function(c,e) .. end; } и вызывается как sw_event[currentEvent]function(c,e) Можно как то от приписки function избавиться? Сразу говорю - ключи у меня будут в переменной, поэтому от скобок не избавиться.
ShadoWalkeR
В идеале хочется sw_event[currentEvent]
ShadoWalkeR
Да - я наврал, в вызове function нет
Snusmumriken
Ммм. handler = {} function handler.plus(a, b) return a + b end function handler.minus(a, b) return a - b end function handler.divide(a, b) return a / b end function handler.multiply(a, b) return a * b end function control(action, a, b) return handler[action] and handler[action](a, b) or 'No handler' end
Snusmumriken
Ща разберусь
ShadoWalkeR
Кстати а в lua есть какие нибудь блоки? Чтобы ключ не функцией являлся а просто куском вышестоящего кода.
ShadoWalkeR
Ну то есть чтото вроде такого return begin end; А при вызове в место вызова содержимое между begin и end просто как часть кода вставлялась
mihacooper [МСК -2]
Это называется "синтаксический сахар", а не извращения. И потребность в нем вполне себе естествена, но нет, Lua не могет
ShadoWalkeR
Жаль. Было бы удобно)
mihacooper [МСК -2]
в том числе для объявления функции
ShadoWalkeR
В руби просто такое есть - можно блок инструкций встаивать в другое место в коде
mihacooper [МСК -2]
как например упрощенный синтаксис для лямбд
mihacooper [МСК -2]
был бы очень кстати
Ivan
ну блок инструкций можно засунуть в функцию и передавать функцию
ShadoWalkeR
Ну я выше так и делаю
Ivan
всё правильно делаешь
ShadoWalkeR
Имелось в виду упрощенный синтаксис - чтобы не обертывать в функции
Ivan
я кажется тебя понял
Snusmumriken
Хмм. Ну я делал вот такое: local template = 'return function(%s) return %s end' local buffer = setmetatable({}, {__mode = 'kv'}) local function arrow(expression) expression = expression:gsub(' ', '') if buffer[expression] then return buffer[expression] end buffer[expression] = loadstring(template:format(expression:match('(.-)=>(.*)')))() return buffer[expression] end a = arrow'a, b => a + b' print(a(10, 20)) --> 30 С буферизацией/кешем.
Ivan
ну ты можешь передать функцию
Ivan
caller(function() end)
Sergey
ребзя
Ivan
function caller(foo) foo() end
Sergey
пишете на luvit?
ShadoWalkeR
Кстати, может предложить в новую версию Lua что инструкции обернутые в конструкцию return begin .. end встраиваются в место вызова. Если не ошибаюсь как выше сказали простая анонимная лямбда
ShadoWalkeR
Ну как в моем случае выше - мне просто нужно менять последовательность действий в зависимости от события. Я конечно делаю как положено, но хотелось бы чтобы немного удобней было)
mihacooper [МСК -2]
проблема не в том, что это не выполнимо в Lua, просто многословно
Ivan
local functionsList = {} for i = 1, 5 do table.insert(functionsList, function() print(i) end) end functionsList[3](); -- 3
ShadoWalkeR
Есть local sw_event = { ["CallLimit"] = function(c,e) app.NoOp("Call limit exceeeded"); app.Ringing(); app.Progress(); app.Playback("vm-isunavail,noanswer"); app.Busy(3); end; ["UserNotFound"] = function(c,e) app.NoOp("User not found in kamailio"); app.Ringing(); app.Progress(); app.Playback("pbx-invalid,noanswer"); app.Busy(3); end; } if Event then sw_event[Event](contex,exten); end;
ShadoWalkeR
Предлагаю local sw_event = { ["CallLimit"] = return begin app.NoOp("Call limit exceeeded"); app.Ringing(); app.Progress(); app.Playback("vm-isunavail,noanswer"); app.Busy(3); end; ["UserNotFound"] = return begin app.NoOp("User not found in kamailio"); app.Ringing(); app.Progress(); app.Playback("pbx-invalid,noanswer"); app.Busy(3); end; } if Event then sw_event[Event]; end;
ShadoWalkeR
Это пример как я сейчас сделал, и как хотелось бы
Ivan
вроде чувак это хотел, они анонимные
Ivan
он хотел это
ShadoWalkeR
Мне не нужно генерировать функцию и передавать параметры в нее, и вызывать потом с параметрами
Ivan
чувак, пиши три символа ` до начала блока кода и после. Телеграм преобразует это в моноширинный текст
ShadoWalkeR
Ну ок - хочу ненужного 😃
Ivan
не знаю, когда действительно нужна анонимность функций, я предпочитаю писать, что она делает
ShadoWalkeR
В руби с этим проще - там блок объявляется как {..} )))
Ivan
то есть я бы написал table.insert(functions, checkEnemys) чем table.insert(functions, function() end))
Ivan
я против анонминости
Ivan
это снежный ком, сначала люди будут писать функции которые умещаются в 1 строчку
Ivan
потом в две
Ivan
потом полотна бля будут передавать
Ivan
ладно, это холивар, но просто увидив название функции ты поймёшь, что она означает
Ivan
мне повезло видеть монструозные конструкции из лямбд лямбд в лямбдах, и все это в вызове функции
Ivan
отлаживать тяжело просто
Ivan
все верно. Допустим ты скажешь, что анонимная функция не должна занимать больше 1 строчки
Ivan
но у него она просто не влезет тогда при отображении в гитлабе, например
Snusmumriken
Ммм.. Едет лямбда через лямбду, видит лямбда - лямбда в лямбде. Сунет лямбда лямбду в лямбду Лямбда лямбда лямбда лямбда.
Ivan
другой подумает. О! можно так делать
Ivan
давай ебашить в две строчки
Snusmumriken
mihacooper [МСК -2]
Так ты же сам написал про надобность анонимных функций) Или ты имеешь ввиду как сделать синтаксис проще?
mihacooper [МСК -2]
ну т.к. он немного коробит своей длинной) по современным мекрам, так сказать
mihacooper [МСК -2]
по сравнению, например с Kotlin, где можно: {it -> it + 1 }
mihacooper [МСК -2]
или примерно так же в JS
Ivan
это всё понты
mihacooper [МСК -2]
да нет же, это же просто другой способ написания
mihacooper [МСК -2]
и чем меньше букав тем проще
mihacooper [МСК -2]
это потому и есть "сахар", что сути не меняет
ShadoWalkeR
Ну иногда нет смысла называть функцию - я выше писал что у меня задача просто по событию встроить в место вызова последовательность шагов. Что и почему делается - видно из названия события
mihacooper [МСК -2]
хаха
Ivan
it -> it + a -> 124 * b -> c -> 124* 124 * 2
ShadoWalkeR
И для вызова тоже нужно параметры указывать
ShadoWalkeR
Да я уже все функциями сделал - лень переделывать)
Snusmumriken
Карочи, у меня некоторые товарищи пишут вот такие штуки, типа: self:Task"Response""Mashine1""Format"{ data = {abc}, error = {cde} } И эту хреновину типа можно использовать по разному: не указал формат - отправило с дефолтным форматом, не написал машину - отправило дефолтной машине, и т.п. Но вот ведь незадача: там функция которая возвращает функцию возвращает функцию, и это чудовищно при отладке. И проще было бы просто список конкретных слов в виде таблицы, хотя бы такое: self:Task{ type = 'Response', To = 'Mashine1', Data = {...}, Format = 'ABC' } Надёжность и читаемость повышается в десятки раз.
Vasiliy
о вот вам еще луа кода: CLASS: GUIButtonBase ( GUIWidget ) :MODEL{ '----'; Field 'msg' :string(); Field 'data' :string(); '----'; Field 'eventTag' :string(); '----'; }
Snusmumriken
Ну, тут так же как в сишке, в которой можно заворачивать указатели на указатели через указатели. Все ограничения - на твоей совести.
Vasiliy
ну вот зачем можно разделять записи в таблице запятой и точкой с запятой?
Snusmumriken
У меня есть стайлгайд которого я придерживаюсь, под названием "Не писать стрёмные штуки, потому что люди же смотрят", и у меня сплошь дедовские способы, чем проще тем лучше.
Ivan
у меня отладкоцентричный подход выработался
Ivan
я предпочту написать так A a = fa(); B b = a.fb(); C c = b.fc(); чем С с = fa().fb().fc();
Snusmumriken
Хе. А я предпочту вот так: a = assert(fa(), 'No Fa!') b = assert(a.fb(), 'No Fb!') c = assert(b.fc(), 'No Fc!')
Snusmumriken
Чтобы дропнуло где надо, типа, желательно с человеческим текстом ошибки.
Ivan
ээээээ
Ivan
ассерт же ничего не возвращает
Snusmumriken
Возвращает первый аргумент