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, просто многословно
Sergey
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
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();
'----';
}
ShadoWalkeR
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
Возвращает первый аргумент