Денис
Snusmumriken
мелочёвку норм конкатить
Денис
Да ну нафиг читать всякое! Я лучше у вас спрошу! 😀
Денис
Вон, тут попросили ООП намутить. Намутил. Надо будет вам на растерзание сбросить, чтобы понять чего там не так.
Vyacheslav
Функция выглядит вот так:
function string.joinsep(orig, sep, ...)
sep = sep or ""
local result = {}
table.insert(result, orig)
for _, field in ipairs(table.pack(...)) do
table.insert(result, field)
end
return table.concat(result, sep)
end
Чем вот так будет плохо?
function string.joinsep(orig, sep, ...)
return table.concat({orig, ...},sep)
end
Snusmumriken
И оно будет неправильно работать при nil'ах в orig или "...", вот эта штука правильно вернёт правильные ошибки.
table.concat((table.pack or pack)(orig, ...), sep)
Vyacheslav
Из минусов - одна аллокация таблицы, но с этим можно жить, имхо.
Vyacheslav
Логичнее с моей точки зрения было бы добавить что-то вроде
function string.join(sep, ...)
return table.concat({...}, sep)
end
Использование:
(","):join("a","b","c")
Vyacheslav
Скорость работы при использовании конкатенации будет уже зависеть от размера строк. Случай использования таблицы не самый быстрый, но без таких "подводных камней"
Snusmumriken
Разумеется.
Snusmumriken
Но эвристика показывает что joinsep'ом куда чаще будут объединять маленькие строчки.
Они даже не в таблице, чел.
Snusmumriken
Если хочешь расширить, посчитай сумму байтиков в склеиваемых строчках, можешь заточиться под это, и если конечный объём меньше килобайта а количество элементов меньше десятка — использовать склейку, а если больше — тейбл.конкат.
Всё в твоих руках.
Vyacheslav
Но эвристика показывает что joinsep'ом куда чаще будут объединять маленькие строчки.
Они даже не в таблице, чел.
Интересно было бы послушать, как вы применяли эвристику и методологию замеров скорости. Спрашиваю оттого, что любая строка, созданная в Lua попадает в weak reference внутренний словарь строк, откуда потом будет вычищаться сборщиком мусора. table.concat продуцирует ровно одну строку.
Оператор .. также продуцирует одну строку.
table.concat в зависимости от параметров сборки Lua может брать блокировку на стейт машину Lua.
.. так не делает.
Не в этом ли может быть ускорение? (Что не учитывается сбор мусора и использование сборки с блокировкой)
Snusmumriken
Создание таблички неизвестного размера и её переразметка делает примерно то же самое.
Vyacheslav
Так в случае {...} размер известен
Snusmumriken
Если добавить функционал table.new(select("#", ...), 0), то было бы проще, табличка с однократной разметкой.
Snusmumriken
Snusmumriken
Байзевей никогда не пакуй туплы в {...} напрямую, только через table.pack который нормально переносит все значения и добавляет ключ n, а table.unpack вполне себе использует этот ключ и возвращает ровно тот тупл который был запакован.
Vyacheslav
Snusmumriken
В ней должна быть не {...} а table.pack(...). Проверь наличие ключа arg.n.
Vyacheslav
Ну ссылку на документацию по Lua-то можно?
Snusmumriken
Не а, ты новичок
Snusmumriken
После суток можно будет
Vyacheslav
Из консоли Termux arg сейчас не даёт использовать.
Не у компьютера, чтобы проверить
Vyacheslav
Тут как раз по делу
lua.org/pil/5.2.html
Vyacheslav
Как было в 5.2
Lucky
Snusmumriken
Snusmumriken
Этот arg — это аргументы командной строки при запуске приложения, это не локальные аргументы функции.
Igor
Надо будет чекнуть байткод.
очень вряд ли при создании таблицы из вариативки берётся размер самого варарга, процентов на 90 уверен, что там реаллокация
Snusmumriken
Качаю блин 5.2
Vyacheslav
В глобальном неймспейсе - да, в вариадик - нет
Snusmumriken
Vyacheslav
Качаю блин 5.2
Только в неинтерактивном режиме надо проверять. В терминале не работает
Snusmumriken
Омг
Vyacheslav
Не из консоли, а с файла только
Vyacheslav
Консоль так не работает от чего-то. Консоль цепляет глобал как раз
Snusmumriken
Vyacheslav
Snusmumriken
print(_VERSION) ?
У тебя блин скриншот, или ты думаешь я обманываю? )
_VERSION тоже можно переписать кста.
Но я только что скачал бинарь для 5.2.4, можешь сделать то же самое.
Vyacheslav
Snusmumriken
Вот это очень странно, потому что в 52.exe никак не может подгружать 53.dll если в нём самом не прописаны фолбеки. Имя шаред либы должно быть совершенно конкретное, иначе бы все либы а ля openal32 и openal64 пытались бы подгружать друг друга с закономерным результатом.
Vyacheslav
Люди вот такое вытворяют, поэтому я не удивляюсь, а лишь проверяю
stackoverflow.com/q/40547638/1836540
Snusmumriken
Зависит от того, как выполнен отладчик. Отладчик Lua может быть привязан к конкретной версии. Если нет отладчика в запуске, то у меня только вопрос про конкретный релиз 5.2. Может, Роберт удалил этот arg при обновлении.
И я не хотел бы спорить насчёт {...} vs pack. У каждого свои предпочтения. Насчёт скорости, соглашусь, что нужно замерять.
И я не хотел бы спорить насчёт {...} vs pack. У каждого свои предпочтения.
Тут нет предпочтений.
{...} не позволяет точно распаковать наборы значений вроде {1, 2, nil, 5, nil, nil}.
# не сможет определить длину, споткнувшись о случайный nil, потому что использует бинарный поиск.
ipairs споткнётся об первый же nil.
pairs/next определит только граничные не-nil-значения, он не в курсе что там есть хвост из nil'ов.
Поэтому есть только два способа упаковывать варарги в таблицу
— pack или
— вручную перебирать через select, плюс указать точное значение элементов, то есть вручную сделать то же что делает pack.
ВСЕ другие способы приводят к потерям данных.
Точка.
Vyacheslav
И я не хотел бы спорить насчёт {...} vs pack. У каждого свои предпочтения.
Тут нет предпочтений.
{...} не позволяет точно распаковать наборы значений вроде {1, 2, nil, 5, nil, nil}.
# не сможет определить длину, споткнувшись о случайный nil, потому что использует бинарный поиск.
ipairs споткнётся об первый же nil.
pairs/next определит только граничные не-nil-значения, он не в курсе что там есть хвост из nil'ов.
Поэтому есть только два способа упаковывать варарги в таблицу
— pack или
— вручную перебирать через select, плюс указать точное значение элементов, то есть вручную сделать то же что делает pack.
ВСЕ другие способы приводят к потерям данных.
Точка.
t={...}; return #t
вернёт длину без хвостовых nil. Это единственное, что может потеряться при сравнении с pack.
В языке, где лишние параметры функций просто отбрасываются, считаю это разумным компромиссом.
function g(v) end
g(1,2,3)
Кроме этого, в случае pack в дополнение к выделению памяти под индексную часть будет выделение памяти под key-value хранилище (хэш) ключей в таблице — под ключ "n".
В случае {...} выделяется только память под индексную часть.
Оттого эта {...} конструкция и существует, логично вписываясь в сделанные компромиссы при реализации интерпретатора и концепцию языка.
Vyacheslav
Вводить ли в code style какой-то конкретной компании или проекта требование использовать pack вместо {...}, по моему мнению, — дело авторов проекта или технического менеджмента компании. Я уважаю ваш выбор, если вы предпочитаете pack, и даже если будете рекомендовать его новичкам. Я лишь против навязывания вида "Тут нет предпочтений."
Я понял, что у вас их нет, но они могут быть у других разработчиков.
Vyacheslav
Господа и, если таковые присутствуют, дамы! С новым годом всех!
Полез я тут, значится, почитать про оптимизацию кода в Lua и наткнулся на сайт ComputerCraft. В частности, на вот эту статью. Увидел про упоминание тернарных операторов и пошел читать. Как говорится, век живи, век учись! До сегодняшнего момента я, честно говоря, не совсем понимал как это работает, а ларчик-то простой и гибкий, оказывается! Из всех приколов я использовал только or при переборе значений и реализацию опциональных параметров. Но, знаете ли, там можно пойти еще глубже! И это охренеть как круто!
Про оптимизацию, я подозреваю, что сказано не все.
Соглашусь про сомнимельность.
a and b or c опасная вещь, т.к. не является стандартным тернарным a?b:c оператором (отличия в случаях, если какой-то из аргументов может быть nil)
Vyacheslav
потоковое чтение для json не сделать, т.к. только дойдя до конца можно понять, что коллекция/массив в json валидная.
Но есть jsonl, который можно по-строчно парсить, именно что в поточном режиме
В общем общем случае можно, в виде автомата состояний, но на выходе будет поток вызовов beginobject, endobject, beginarray, endarray, newkey, newtoken etc.
И в процессе их "проигрывания" не будет известно, валидный ли JSON пришёл на вход. Это знание появится на последнем вызове endobject, если он произойдёт.
Денис
А если джойнить через string.format? Составить шаблон через string.rep и ухнуть в нее инфинити? Насколько это будет быстро по наблюдению?
Денис
Хотя, чему там тормозить. . . Сишное все. Памяти потратится только на шаблон, чанки в параметрах и результирующую строку.
Денис
А и вообще, стоит ли на это задрачивать?.. пишу не для маленьких железок, расчет на бытовые компы. . . Когда буду писать под что-то маломощное, тогда и буду оптимизировать все, что движется. . .
Snusmumriken
t={...}; return #t
вернёт длину без хвостовых nil. Это единственное, что может потеряться при сравнении с pack.
В языке, где лишние параметры функций просто отбрасываются, считаю это разумным компромиссом.
function g(v) end
g(1,2,3)
Кроме этого, в случае pack в дополнение к выделению памяти под индексную часть будет выделение памяти под key-value хранилище (хэш) ключей в таблице — под ключ "n".
В случае {...} выделяется только память под индексную часть.
Оттого эта {...} конструкция и существует, логично вписываясь в сделанные компромиссы при реализации интерпретатора и концепцию языка.
Чел..
Ты слышал что-то про бинарный поиск?
Пора привыкнуть, что если я что-то говорю, под это существуют совершенно конкретные объективные причины, и если я ДЕСЯТЬ раз повторяю одно и то же — значит это проверено многократно и я тут в своё время успел обосраться раза три.
table.len использует тот же самый тот же бинарный тот же поиск, поэтому смухлевать не получится.
На тему хвостовых nil — от них может зависеть логика, например в местах где отправка nil'ов чаще приводит к ошибкам, и надо ругнуться "чел ты мне nil послал последним аргументом, почему всё таки послал а не опустил этот аргумент?".
Vyacheslav
Vyacheslav
Чел..
Ты слышал что-то про бинарный поиск?
Пора привыкнуть, что если я что-то говорю, под это существуют совершенно конкретные объективные причины, и если я ДЕСЯТЬ раз повторяю одно и то же — значит это проверено многократно и я тут в своё время успел обосраться раза три.
table.len использует тот же самый тот же бинарный тот же поиск, поэтому смухлевать не получится.
На тему хвостовых nil — от них может зависеть логика, например в местах где отправка nil'ов чаще приводит к ошибкам, и надо ругнуться "чел ты мне nil послал последним аргументом, почему всё таки послал а не опустил этот аргумент?".
Если вы хотите опровергнуть мои утверждения про {...}, то используйте {...}, пожалуйста, а не оператор инициации таблицы.
Vyacheslav
На тему хвостовых nil/ не-nil, я привёл аргумент, что так же невозможно в вызываемой Lua-функции с фиксированным числом параметров проверить, что передано больше параметров, чем нужно.
Snusmumriken
Snusmumriken
И есть только один варик для этого — pack.
Если ты вдруг не знаешь, люди обычно стараются не избегать UB любой ценой.
Igor
UtoECat
Snusmumriken
Например, возьмём ловку.
Конструкция вида
love.graphics.draw(img, x, y, _, _, _, 32, 32)
встречается регулярно, потому что впадлу заполнять аргументы по дефолту.
И кстати, там luajit (5.1).
Что было бы если ловка паковала это как варарги в табличку и итерировала бы по ним?
Она бы обосралась в 5.1 без pack'а.
Alxius
сделал я наконец чтобы выстрел кислоты влиял слабо очень на дроида и слабее на танка. при этом не поломав эффект коррозия. . так что игра Colony станет значительно легче. https://dj-alex.itch.io/colony В иобщем геймплей теперь будет менее хардкорным в ней. Билд 273 выбирать
Alxius
ранее я убавлял убавлял урон врагам. а он не убавлялся, потому что убивал не урон а навешанные дебаффы (яд) просто постоянно -1 отнимал.
Snusmumriken
Яды это вообще бич кучи старых игр
Snusmumriken
Ну там, где-то в далёком 98 году приравняли скорость тиков ядов к фреймрейту.
На старом компудахтере игра работает в 20 fps, и там тики нормальные. На современном 600 fps и яды шотают, стоит мизинчиком наступить в лужицу. Или нечто аналогичное.
UtoECat
Например, возьмём ловку.
Конструкция вида
love.graphics.draw(img, x, y, _, _, _, 32, 32)
встречается регулярно, потому что впадлу заполнять аргументы по дефолту.
И кстати, там luajit (5.1).
Что было бы если ловка паковала это как варарги в табличку и итерировала бы по ним?
Она бы обосралась в 5.1 без pack'а.
Хмм... Не думал, что это так может работать 😐. Обычно я все дефолтные аргументы прописываю полностью... Оно и читается потом легче, не надо додумывать что там должно быть... Но всё равно интересно.
Snusmumriken
Я просто даю пример где бы был обсёр.
Понятное дело что сама ловка не использует варарги в таких местах.
Snusmumriken
Но она использует варарги в функциях вроде полигона, и вот там, если вдруг встретился nil — это явная ошибка, которая может быть пропущена в случае использования чего-то {...}-подобного, и хрен отладишь и хрен поймёшь почему это у тебя рисуется только кусок полигона вместо целого.
UtoECat
Alxius
Alxius
Но возможно реально надо фпс и скорость игры учитывать