GETTABUP 0 0 -1 ; _ENV "print" LOADK 1 -2 ; "Hello, Lua" CALL 0 2 1 RETURN 0 1
Я использую Lua уже несколько лет — я использовал его как кроссплатформенный язык сценариев, язык сценариев для игр, для создания приложений Linux, IRC-ботов, веб-серверов и всего остального, что только можно вообразить, но я продолжаю наблюдать одну постоянную тенденцию: Людям не нравится использовать Lua.
Почему люди не любят использовать Lua? Причин много, некоторые из них описаны в этой статье Тима Менша:
- LuaJIT сейчас находится в режиме обслуживания, никаких серьезных изменений выпущено не будет.
- У Lua есть несколько версий, которые имеют различия.
- Очевидно, у JavaScript лучшая экосистема.
- Lua Coroutines больше не монополия.
- По-видимому, требуются аннотации типов.
Теперь, риторически, почему любой из них является причиной покинуть Lua? Программа, которая не хочет выпускать какие-либо основные версии, может быть разветвлена любым, кто захочет ее улучшить — к тому же такие проекты, как Ravi и LLVM-Lua, создают компиляторы Lua, оптимизированные для LLVM, так в чем же проблема? Что касается второй версии, многие языки имеют разные версии, которые не имеют обратной совместимости. Python имеет разницу между 2 и 3; JavaScript (на который вы часто будете слышать, как я жалуюсь) даже имеет транспилятор, чтобы сделать исходный код обратно совместимым. Что касается третьего пункта, у JavaScript гораздо больше пакетов, но это потому, что у JavaScript есть «ощущение», которое требует большого количества программных зависимостей. Для одного программного обеспечения (например, Polymer) нужно было бы установить десятки пакетов всего для нескольких элементов. Lua с меньшим количеством элементов, которые нужно поддерживать, никогда не было проблемой, потому что программное обеспечение работает и делает то, что нужно.
Я не считаю, что последние два пункта, перечисленные в списке, являются какими-либо проблемами. Тот факт, что одно программное обеспечение использует определенную технологию, не означает, что другое программное обеспечение не может иметь эту технологию и, следовательно, делает первое программное обеспечение менее ценным. Что касается последнего элемента, аннотации типов существуют в таких форматах, как Typed Lua и Ravi — первый из них компилируется с помощью Lua, а второй является специальным дополнением к виртуальной машине Lua 5.3. TypeScript действует так же, как Typed Lua, где Ravi на самом деле работает быстрее из-за соединений типов, выполняемых на стороне C. Ни один из этих пунктов не должен быть определяющим фактором языка, если оба языка имеют эти особенности.
Я начал эту статью со слов «Привет, Луа». Я хотел бы представить некоторые вещи, которые делают Lua языком, который, я считаю, делает его не имеющим аналогов среди других языков:
Луа это просто
Вы когда-нибудь смотрели на программу и думали: «Черт, это почти похоже на псевдокод или что-то, что я мог бы произнести вслух»? Если да, то вы, вероятно, использовали Lua раньше. Lua — один из самых читаемых языков программирования благодаря упрощенным правилам грамматики. Когда я пишу приложение на Lua, мне кажется, что я пишу документ. Большую часть времени я не документирую большую часть своего кода, потому что мне кажется, что он документирует сам себя из-за простоты. Англоподобная природа Lua делает его чрезвычайно удобочитаемым и простым для написания языком.
Луа быстрый
По сравнению со многими другими языками Lua и особенно LuaJIT оставляют эти языки далеко позади. Lua — очень простой язык, как и C, и из-за этого все делается с чрезвычайно высокой скоростью. Иногда LuaJIT работает даже быстрее, чем C. Из-за JIT-компиляции и простоты Lua является одним из самых быстрых языков, ноздря в ноздрю с JavaScript и C.
Связать ОЧЕНЬ легко
Допустим, у вас есть функция на C, но вы хотите вызвать ее в своем приложении Lua. В качестве примера мы будем использовать функцию POSIX fork(). Сначала мы вызываем функцию и сохраняем возвращаемое значение — целое число. Затем мы помещаем это целое число в стек Lua, чтобы его можно было вернуть из функции. Затем мы возвращаемся из функции, и виртуальная машина Lua возобновляет выполнение кода Lua.
int lua_fork(lua_State *L) { int fork_result = fork(); lua_pushinteger(L, (lua_Integer)fork_result); return 1; }
Создание библиотеки Lua также чрезвычайно простой процесс. Вы связываете имена с функциями, а затем вызываете функцию, которая помещает результат в стек Lua, после чего библиотека становится доступной через виртуальную машину Lua.
static const struct luaL_Reg fork_lib[] = { {"fork", lua_fork}, {NULL, NULL} } int luaopen_util(lua_State *L) { luaL_newlib(L, fork_lib); return 1; }
В Lua вы можете запросить эту библиотеку как «util» и вызвать функцию fork().
Интерфейс внешней функции
Если вы не являетесь поклонником функций привязки или не хотите компилировать библиотеку, вы также можете использовать стороннюю библиотеку интерфейса функций, например, встроенную в LuaJIT и внешнюю, портированную Facebook, luaffifb. . В качестве примера мы свяжем функцию fork(), как показано в предыдущем примере.
local ffi = require("ffi") ffi.cdef[[int fork();]] ffi.C.fork()
Используя этот базовый пример, вы теперь имеете системный вызов fork() на Lua с выполнением всего трех строк кода.
Несколько языковых «форков»
Одним из преимуществ JavaScript является использование нескольких транспиляторов и компиляторов. Некоторые люди предпочитают CoffeeScript, в то время как другие предпочитают TypeScript. Другие просто используют обычный JavaScript и используют Babel, чтобы сделать его обратно совместимым.
Аналогичным образом Lua предлагает несколько транспиляторов и языковых дистрибутивов. Одним из самых популярных транспиляторов является MoonScript — язык, вдохновленный CoffeeScript. Некоторые другие среды выполнения включают Ravi, опционально со статической типизацией и LLVM-компилируемой Lua, и Terra, смесь Lua и C.
Теперь, когда у меня есть несколько простых причин, почему Lua — хороший язык, я хотел бы поделиться некоторыми вещами, которые легко выполнимы в Lua:
Системные служебные команды
Раньше написание системных команд выполнялось только на одном языке: C. Теперь мы можем использовать другие языки, такие как Perl, Python и (как вы уже догадались) Lua. Системные команды можно легко запрограммировать на Lua. В качестве примера я напишу пример команды `echo`:
#!/usr/bin/env lua local has_end_of_line if arg[1] == "-n" then has_end_of_line = true table.remove(arg[1]) end io.write(table.concat(arg, " "), has_end_of_line and "\n" or "")
Поздравляем! Это системная команда, написанная на Lua! С большей сложностью вы, вероятно, могли бы заменить все пакеты coreutils Linux программами Lua.
IRC-боты
Если бы я стрелял каждый раз, когда запрограммирован IRC-бот, я был бы мертв. Это все, что я скажу по теме. Однако, если хотите, вот IRC-бот, который я сделал.
Программное обеспечение для работы с текстом
Существует множество способов использования Lua для управления текстом. Однако в этом документе мы продемонстрируем только язык конфигурации, использующий только шаблоны Lua — язык, подобный INI.
local function read(input) local output = {} local current = output while true do local line = coroutine.resume(input) if not line then break end if line:match("^%[[^%]]+%]") then -- [x] key = line:match("^%[([^%]]+)%]") output[key] = output[key] or {} current = output[key] elseif line:match("^[^=]+=.+") then -- key=value local key, value = line:match("^([^=]+)=(.-)%s*$") current[key] = value end end return output end
Теперь все, что вам нужно сделать, это вызвать read() с сопрограммой, и ваш INI будет проанализирован в таблицу Lua.
Я бы добавил синтаксический анализатор JSON, но этот документ уже достаточно длинный. Извините, JSONers. Может быть, в следующий раз.
В дополнение к настройке шаблоны Lua могут быть полезны для сопоставления абстрактных шаблонов, таких как этот парсер тегов IRCv3 daurnimator, который я сделал:
parse_tags = (tag_message)=> local cur_name tags = {} charbuf = {} pos = 1 while pos < #tag_message do if tag_message\match '^\\', pos lookahead = tag_message\sub pos+1, pos+1 charbuf[charbuf+1] = escapers[lookahead] or lookahead pos += 2 elseif cur_name if tag_message\match "^;", pos tags[cur_name] = table.concat charbuf cur_name = nil charbuf = {} pos += 1 else charbuf[#charbuf + 1], pos = tag_message\match "([^\\;]+)()", pos else if tag_message\match "^=", pos if #charbuf > 0 cur_name = table.concat charbuf charbuf = {} pos += 1 elseif tag_message\match "^;", pos if #charbuf > 0 tags[table.concat charbuf] = true charbuf = {} pos += 1 else charbuf[#charbuf + 1], pos = tag_message\match "([^\\=;]+)()", pos return tags
Это довольно сложный шаблон, но он выполняет свою работу.
Веб-серверы
Так много бога проклятых веб-серверов. Очевидно, что-то должно идти правильно, если их так много. Я имею в виду, что Lua быстр, эффективен и идеально подходит для облегченных сценариев, а также, по-видимому, хорош в качестве основного бэкенда для веб-сервера. Я не эксперт, но скажу, что Lua явно сделал что-то правильное, чтобы привлечь внимание создателей веб-серверов.
Это лишь некоторые примеры того, что было сделано и может быть сделано в Lua. Я призываю других людей дополнять этот список и демонстрировать возможности Lua.
Сноска
Пожалуйста, ради любви к Lua, не присылайте мне гневные письма, потому что я «оскорбляю другие языки». Я не пытаюсь сказать, что Python или Perl — отстой, или что JavaScript — отстой из-за ужасной экосистемы (о, подождите, да, но только отчасти). Мне нравится использовать Python и раньше, а также поддерживать программное обеспечение, которое использует Python в настоящее время. Я немного поработал с Perl и C++. Я до сих пор использую C, а также Lua. Я также иногда использую JavaScript для одного или двух веб-приложений. Пожалуйста, не принимайте это за то, что я ругаю другие языки. Я просто пытаюсь указать на некоторые положительные стороны Lua.