Lua — это, пожалуй, мой любимый "маленький язык", с низкой когнитивной нагрузкой и простотой в изучении и использовании. Он встроен во многое ПО, такое как Redis, NGINX через OpenResty и Wireshark (прим. перевод.: и многие другие). Он также используется в качестве скриптового языка в таких играх, как World of Warcraft и Roblox через Luau (прим. перевод.: и многих других). Этот пост — краткое признание в любви языку с некоторыми примерами того, почему он мне так нравится.

Логотип языка программирования Lua
Логотип языка программирования Lua

Простота

В Lua относительно немного фич и относительно мало синтаксиса. К примеру, в языке всего 8 типов:

  • nil

  • boolean

  • number

  • string

  • userdata (для представления С-шных структур данных или блоков памяти в куче)

  • function

  • thread (для корутин)

  • table (ассоциативный массив и, по совместительству, единственная встроенная структура данных)

Нет нужды беспокоиться о float, int, usize. Нет нужды беспокоиться о различиях в массивах, словарях и структурах. Даже классы тут это просто таблицы (table) с указанными мета-таблицами (metatables, прим. перев.: думайте о прототипах, как в JavaScript). Такая простота во всём делает Lua лёгким в освоении и использовании, обеспечивая при этом достаточную мощь для выполнения большинства необходимых задач.

Давайте реализуем простой бинарный поиск по массиву на Lua:

-- однострочные комментарии начинаются с двух тире

function binary_search(array, value)
    local low = 1
    local high = #array -- # это оператор взятия длины

    while low <= high do
        -- доступ к библиотечным функциям через глобальную таблицу
        local mid = math.floor((low + high) / 2)
        local mid_value = array[mid]

        if mid_value < value then
            low = mid + 1
        elseif mid_value > value then
            high = mid - 1
        else
            return mid
        end
    end

    return nil
end

res = binary_search({2, 4, 6, 8, 9}, 6)
print(res)

Всё это должно быть относительно знакомо, даже если вы никогда раньше не сталкивались с Lua. Единственное, что может показаться непривычным, это ключевое слово local, которое используется для объявления переменных (прим. перев.: и не только). По умолчанию все они глобальны, так что local используется для объявления локальной переменной относительно текущей области видимости.

Транспиляция

Lua является великолепной целью для транспиляции, благодаря его простоте и лёгкости взаимодействия с C. Поэтому, Lua - отличный выбор для предметно-ориентированных языков (DSL-ей), таких как Terra, MoonScript и Fennel.

В качестве краткого примера, вот тот же бинарный поиск написанный в MoonScript и Fennel соответственно:

Код
binary_search = (array, value) ->
    low = 1
    high = #array

    while low <= high
        mid = math.floor((low + high) / 2)
        mid_value = array[mid]

        if mid_value < value
            low = mid + 1
        else if mid_value > value
            high = mid - 1
        else
            return mid

    return nil

print binary_search {2, 4, 6, 8, 9}, 6
(fn binary-search [array value]
  (var low 1)
  (var high (length array))
  (var ret nil)
  (while (<= low high)
    (local mid (math.floor (/ (+ low high) 2)))
    (local mid-value (. array mid))
    (if (< mid-value value) (set low (+ mid 1))
        (> mid-value value) (set high (- mid 1))
        (do
          (set ret mid)
          (set low high)))) ; no early returns in Fennel
  ret)
(local res (binary-search [2 4 6 8 9] 6))
(print res)

Встраиваемость

Но истинная сила языка заключается в том, что вы можете внедрить его практически куда угодно - Lua реализован как библиотека для программы-хоста, типа Redis. Традиционно, это была программа на C, но теперь существуют многие реализации виртуальной машины Lua в разных языках, таких как Javascript (с Fengari) или Go (c GopherLua). Однако, одной из самых популярных реализаций является скриптовый язык Luau для игры Roblox.

Возможно, одно из моих любимых применений Lua — это HAProxy, возвращающий нас во времена Apache + mod_php скриптинга. Давайте настроим конфигурацию HAProxy, которая будет отвечать на запросы по определённому пути случайным предсказанием:

Код
local function fortune(applet)
    local responses = {
        {
            quote = "The only people who never fail are those who never try.",
            author = "Ilka Chase"
        },
        {
            quote = "The mind that is anxious about future events is miserable.",
            author = "Seneca"
        },
        {
            quote = "A leader is a dealer in hope.",
            author = "Napoleon Bonaparte"
        },
        {
            quote = "Do not wait to strike until the iron is hot; but make it hot by striking.",
            author = "William B. Sprague"
        },
        {
            quote = "You have power over your mind - not outside events. Realize this, and you will find strength.",
            author = "Marcus Aurelius"
        }
    }

    local response = responses[math.random(#responses)]
    local resp = string.format([[
        <html>
            <body>
                <p>%s<br>&nbsp;&nbsp;--%s</p>
            </body>
        </html>
    ]], response.quote, response.author)

    applet:set_status(200)
    applet:add_header("content-length", string.len(resp))
    applet:add_header("content-type", "text/html")
    applet:start_response()
    applet:send(resp)
end

core.register_service("fortune", "http", fortune)
global
    lua-load fortune.lua

defaults
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s

frontend fe_main
    bind :8080
    mode http
    http-request use-service lua.fortune if { path /fortune }

И затем запустим её:

$ haproxy -f haproxy.cfg
$ curl localhost:8080/fortune
    <html>
    	<body>
    		<p>Do not wait to strike until the iron is hot; but make it hot by striking.<br>&nbsp;&nbsp;--William B. Sprague</p>
    	</body>
    </html>

Зачем вообще так делать? Легко вообразить ситуацию, в которой нужна небольшая логика приложения поверх веб-сервера, но вы не хотите писать полноценной веб-приложение под эту задачу. Или же вы хотите расширить функционал существующих приложений, например, добавить небольшой запрос (endpoint) для проверки статуса (healthcheck) Redis-сервера:

Код
-- это сторонний форк redis-lua с поддержкой TLS:
local redis = require("redis-tls")

local settings = {
	host = "127.0.0.1",
	port = 6379,
	database = 14,
	password = nil,
}

local utils = {
	create_client = function(params)
		local client = redis.connect(params.host, params.port, 1, false)
		if params.password then
			client:auth(params.password)
		end
		return client
	end,
}

local function redis_health(applet)
	-- pcall как try/catch, принимает функцию и аргументы,
	-- и возвращает true/false и результат выполнения функции
	local ok, client = pcall(utils.create_client, settings)
	if not ok then
		local string_resp = '{"ok":false}\n'
		applet:set_status(500)
		applet:add_header("content-length", string.len(string_resp))
		applet:add_header("content-type", "application/json")
		applet:start_response()
		applet:send(string_resp)
		return
	end

	local resp = client:ping()
	local string_resp = string.format('{"ok":%s}\n', resp)
	applet:set_status(200)
	applet:add_header("content-length", string.len(string_resp))
	applet:add_header("content-type", "application/json")
	applet:start_response()
	applet:send(string_resp)
end

core.register_service("redis_health", "http", redis_health)
global
    lua-load redis.lua

frontend fe_main
    bind :8080
    mode http
    http-request use-service lua.redis_health if { path /redis_health }

Redis-сервер выключен/лежит:

$ curl 127.0.0.1:8080/redis_health
  {"ok":false}

Redis-сервер работает и доступен:

$ curl 127.0.0.1:8080/redis_health
  {"ok":true}

Можно пойти дальше и использовать register_action и register_fetches (см. доки) для перехвата информации о запросе, его изменения или добавления дополнительных возможностей аутентификации поверх ПО без встроенной системы аутентификации.

Сообщество

Оно не особо велико, но в нём ведётся множество отличных разработок, а многие библиотеки доступны через простой пакетный менеджер LuaRocks. От библиотек для быстрого парсинга и кодировки JSON до дополнений к стандартной библиотеке (прим. перевод.: или даже добавления программируемых компьютеров в Minecraft) - для каждого найдётся что-то своё.

Отдельного упоминания заслуживает Лиф Коркоран (Leaf Corcoran), написавший Lapis - фантастический небольшой веб-фреймворк для дистрибутива OpenResty, на котором работает сайт LuaRocks.

Прим. перевод.: В отличие от некоторых сообществ, в Lua нет ни мелких, ни больших скандалов или интриг (см. Rust ????: ^1, ^2, ^3)

Заключение

Есть ли какой-то вывод? Lua очень хорош, вы можете освоить его за выходные и начать использовать его для написания слоёв авторизации в HAProxy, аддонов для World of Warcraft, игр в рамках Roblox, скриптов для вашего оконного менеджера, работы с сетями или просто небольших библиотек, которые делают вас чуточку счастливее.

Прим. перевод.: и не забывайте про игровые движки - Love2D, Defold и интеграция с Raylib.


От себя я бы рекомендовал посмотреть на Fennel, упомянутый выше в переводе. Это LISP, который транспилируется в Lua — вы получаете скорость, простоту и доступность Lua c гибкостью LISP-синтаксиса и макросов.

А для тех, кто только начинает свой путь в программировании, у меня есть промокод HABR23. Где применить не скажу, а то реклама :)

Кстати, я веду Телеграм-канал для заинтересованных в обучении и осмыслении всего в IT, присоединяйтесь, если ещё не!

Комментарии (60)


  1. chernish2
    29.05.2023 20:00
    +10

    Про этот ЯП можно было бы рассказать гораздо больше всего интересного, с примерами и пояснениями.


    1. novusnota Автор
      29.05.2023 20:00

      Согласен. Что бы вам прежде всего хотелось видеть в развёрнутом разборе?


      1. MiraclePtr
        29.05.2023 20:00
        +13

        Что с производительностью? Есть ли варианты интерпретаторов с JIT-компиляцией? Или можно ли транспилировать в Си-код?

        Что с легковесностью, какие самые лёгкие интерпретаторы? (например, можно ли запустить скрипт на восьмибитном контроллере с парой килобайт памяти?)

        Что с управлением памятью? Сборка мусора, refcounting, или все ручками?

        Упомянули корутины - было бы интересно посмотреть, какие они и как сделаны внутри.


        1. novusnota Автор
          29.05.2023 20:00
          +11

          Спасибо за предложения! Вот краткие ответы на некоторые вопросы, пока не написал подробный разбор или не нашёл достойный для перевода:

          Есть ли варианты интерпретаторов с JIT-компиляцией?

          Есть! LuaJIT

          Что с легковесностью, какие самые лёгкие интерпретаторы?

          Стандартный интерпретатор весит 282 Kb, а вся стандартная библиотека — 470 Kb.

          Можно ли запустить скрипт на восьмибитном контроллере с парой килобайт памяти?

          Можно, причём даже делают миниатюрные виртуальные компьютеры с интересными ограничениями — TIC-80

          Что с управлением памятью? Сборка мусора, refcounting, или все ручками?

          Сборка мусора.

          Корутины - было бы интересно посмотреть, какие они и как сделаны внутри

          Отрывок из книги о Lua, про корутины.


          1. event1
            29.05.2023 20:00
            +2

            Стандартный интерпретатор весит 282 Kb, а вся стандартная библиотека — 470 Kb

            Не знаю, что у вас за стандарт такой. У меня такой:

            root@рhost:~# /usr/bin/lua -v
            Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio (double int32)

            root@host:~# ls -lh /usr/bin/lua
            -rwxr-xr-x 1 root root 9.2K Dec 31 1969 /usr/bin/lua

            root@host:~# ls -lh /usr/lib/liblua.so.5.1.4
            -rw-r--r-- 1 root root 171.4K Dec 31 1969 /usr/lib/liblua.so.5.1.4

            И это ещё с поддержкой целочисленной арифметики


            1. novusnota Автор
              29.05.2023 20:00

              Клёво!
              А я имел в виду самую последнюю версию интерпретатора и прямую цитату с официального сайта, в параграфе "Lua is small"


        1. playermet
          29.05.2023 20:00
          +2

          Есть ли варианты интерпретаторов с JIT-компиляцией?

          Они не просто есть. LuaJIT является одним из быстрейших интрепретаторов языков с JIT-компиляцией, и долгое время обгонял супер-оптимизированный V8 для JavaScript от гугла (сегодня это уже не так). А если нужно еще быстрее, то можно определять сишные типы через встроенный модуль FFI, и работать уже с ними.


  1. aborouhin
    29.05.2023 20:00
    +3

    Не оспаривая достоинств Lua... Примерно всé, кто в принципе умеет / готов что-то по мелочи запрограммировать, в наше время ужé знают или Python, или JS. Мне лично несимпатичен ни тот, ни другой, но это факт. И пусть Lua проще / легковеснее их обоих - это всё равно новый язык, который надо освоить, а потом на него ещё и переключать мозги для Lua-специфичных задач, если в основном пишешь на другом языке. Так что если бы сейчас стояла задача внедрить в продукт какой-то скриптинг для продвинутых пользователей - выбирал бы именно между Python и JS (лучше, конечно, универсальное решение с binding'ами к разным языкам, но тут уж от ресурсов зависит).


    1. saboteur_kiev
      29.05.2023 20:00
      +11

      суть луа в том, что его удобно встроить куда-то, в то время как питон (особенно современный 3й) встроить внутрь nginx кажется задачей непомерно громоздкой и неудобной.

      Луа это как PCRE библиотека - удобное для интеграции легковесное и популярное решение.


      1. aborouhin
        29.05.2023 20:00

        Ну систему, где нет python, надо ещё поискать. Хотя для приложений типа nginx или haproxy, которые могут запускаться на минималистичном урезанном дистрибутиве и такой сценарий нормален и важен, - соглашусь. Но в списке софта со встроенным Lua много приложений, для которых таких ограничений нет, и встроить в них можно хоть JRE с .NET на пару, никто особо и не заметит :) А вот за знакомый язык скажет спасибо.

        Смотрю с точки зрения того самого пользователя, которому уже изрядно надоело вникать в очередной язык ради нескольких десятков строчек скрипта, которые надо очередной софтине скормить (а в списке таких языков в моей практике уже побывали и Lua, и Clojure, и Groovy, и вообще своеобычный язык Autohotkey, а про тысячу и одну разновидность query language вообще молчу).


        1. mc2
          29.05.2023 20:00
          +3

          Ну примеров использования языка достаточно, что бы задуматься: Roblox, WoW, Lightroom.

          поискать - embedded системы бывают чувствительны к размеру образа.


          1. AKudinov
            29.05.2023 20:00
            +2

            Мне, кстати, лет 10 назад довелось поработать со встроенной системой, в которой единственным ЯП был Python. То были интегрированные GSM/GPS модули Telit. И вот чтобы железяка могла делать что-то полезное, в неё через последовательный порт по протоколу z-modem заливался файл .py, потом она перезагружалась, несколько минут внутри себя "транслировала" скрипт в двоичный Python object, после чего была готова к работе.
            На всю жизнь запомнилось.


            1. domix32
              29.05.2023 20:00

              А там какой-то стандартный питон или что-то альтернативное было?


              1. AKudinov
                29.05.2023 20:00

                Насколько я тогда мог судить, вполне стандартный. Естественно, никаких дополнительных библиотек ему поставить было нельзя. Были видны несколько объектов для чтения координат из GPS, общения с GSM-модемом с помощью AT-команд и управления внешними линиями GPIO на разъёме. Тогда Python в небольшой плоской коробочке размером 50мм*50мм выглядел, как маленькое чудо.


        1. SuperTEHb
          29.05.2023 20:00
          +2

          Ну систему, где нет python, надо ещё поискать.

          Это вы про большие машины. На моём кэноне нет питона, но зато есть луа. ЕСП8266 всякие тоже отлично работают под управлением луа скриптов. Впрочем, на них есть и микропитон.


          1. iig
            29.05.2023 20:00

            ЕСП8266 всякие тоже отлично работают под управлением луа скриптов.

            Ну, так себе. Интерпретирующий язык, который свалится не при компиляции, а во время работы. Очень многословный (по сравнению с C/C++). Программа то заработала, но удовольствия от процесса нет ;)


            1. SuperTEHb
              29.05.2023 20:00
              +2

              Его можно "скомпилировать" прямо на этом же микроконтроллере! А ещё в прямом эфире команды отправлять. Короче, мне понравилось. Но что нюансов куча это бесспорно.


            1. novusnota Автор
              29.05.2023 20:00

              Присмотритесь к:

              1. Terra — низкоуровневый язык, встраивающийся в Lua и позволяющий легко взаимодействовать с C/C++, причём даже с дженериками и шаблонами последнего!

              2. Nelua – Lua-подобный язык, но с типами и опциональной (!) сборкой мусора, который транспилируется в C или напрямую компилируется в машинный код.


        1. saboteur_kiev
          29.05.2023 20:00
          +2

          Ну систему, где нет python, надо ещё поискать.

          Вы не поняли контекст?
          Система - имеется ввиду встроенный скриптовый язык в вашем приложении, а не отдельно установленное в операционке.

          Вот насколько было бы лучше, если бы в Autohotkey скриптовым языком был бы луа, а не то, что там сейчас?


        1. event1
          29.05.2023 20:00
          +2

          Ну систему, где нет python, надо ещё поискать

          10 лет назад люди впихнули интерпретатор Луа в ядро ОС NetBSD. Питона в такое место засунуть не получится


          1. kovserg
            29.05.2023 20:00
            +4

            Ну систему, где нет python, надо ещё поискать

            Windows7 например


      1. arheops
        29.05.2023 20:00

        https://github.com/arut/nginx-python-module

        Вот же. Python в nginx

        Вообще и python и perl прекрасно встраивается. Много где встроены


        1. orcy
          29.05.2023 20:00
          +1

          Этот модуль разве не потребует установленного питона на машине? В таком случает это не тот уровень встраивания как lua.


          1. arheops
            29.05.2023 20:00
            -1

            Модуль луа тоже liblua требует. Просто оно меньше. А как вы попробуете хоть что-то кроме примеров запрограммить, тут же окажется что вам нужны другие lua библиотеки и биндинги к odbc, к примеру


            1. Mingun
              29.05.2023 20:00
              +3

              Не требует, так как Lua тривиально собирается в статическую библиотеку, или вообще компилируется из исходников при сборке вашего проекта (как встраиваемый sqlite).


              Вот про встроенные батарейки это конечно в точку, на с другой стороны это и преимущество — можно встроить именно сам язык, а не язык со стандартной и не очень библиотекой. Если хотите, то даже math можно не встраивать.


        1. AKudinov
          29.05.2023 20:00
          +1

          Python "встраивается" в том смысле, что можно внутри программы организовать интерфейс, чтобы внешний интерпретатор Python мог в него ходить? По аналогии с COM из мира Windows? Мне кажется, Python слишком тяжёл, чтобы его целиком засунуть внутрь прикладного софта. В отличие от Lua или того же TCL.


          1. arheops
            29.05.2023 20:00
            +1

            Точно так же само, как и луа встраивается. Микро-машина, которая встраиватся в процесс и процессит python-код
            А до этого активно встраивали перл, и это даже активно меняло ядро.


            Честно говоря, сам LUA невероятно тяжел по сравнений с каким-то фортом. Все познается в сравнении.


            1. kale
              29.05.2023 20:00
              +3

              По сравнению с Фортом все тяжелее, кроме ассемблера.


              1. kovserg
                29.05.2023 20:00
                +1

                По сравнению с фортом луа очень высокоуровневый язык.


        1. novusnota Автор
          29.05.2023 20:00

          Версия Python там — 2.7, а кроме того нужно учитывать временной лаг на старт его интерпретатора. Пока Python только будет запускаться, скрипт на Lua уже отработает, особенно если он запущен с использованием JIT компиляции :)


          1. bannedInTheFuture
            29.05.2023 20:00

            По-моему, не надо путать язык (синтаксис и стандартная библиотека) и среду исполнения. Лёгкие рантаймы есть для разных языков, вон даже есть ВМ Java для AVR, вероятно, самого дохлого микроконтроллера из ныне используемых.

            Луа, вроде, зародился в академических кругах, а потом как-то проник в реальную жизнь. И он ничем не лучше других. Даже хуже! Например, JavaScript лучше хотя бы тем что его "всё знают" (кроме питонистов, возможно :) ). Т.е. привычный синтаксис и куча разных рантаймов, например, можно использовать JavaScript внутри программы на Java.

            Что касается статьи.... Ну в Википедии написано больше. Мини то, ни другое не отвечают на вопрос зачем мне учить ещё один язык (а чтобы что-то внятное писать, учить его придётся и то что для этого хватит вечера субботы - маркетинговая коровья лепёшка).


    1. domix32
      29.05.2023 20:00
      +3

      Скажем из Си в питон прибиндиться можно без особой боли, но вот чтобы наоборот - придётся пострадать. Для JS только недавно полноценные легковесные рантаймы появились, для луа они есть уже раза в три дольше. И таки нет такого огромного количества странных поведений, сколько их есть в JS, чем в классическом луа (PUC Rio), поэтому JS - сомнительный выбор для скриптинга. Проще тогда вообще с ним не связываться, а писать сразу на wasm.


  1. Chillingwilli
    29.05.2023 20:00
    +3

    Пожалуй соглашусь с автором выше. Я ожидал более развернутой статьи, но все равно неплохо.


  1. Pastoral
    29.05.2023 20:00
    -3

    Если по найму, то выбирать вредно, как господин начальник сказали, так и будет. Если не по найму, то где больше библиотек, это или Python или JavaScript. А встраивать, тогда Lua хорошо, это высоковат уровень и специфичны задачи.

    Кто понимает что хоть один язык надо знать действительно хорошо и библиотеки ему, в силу оригинальности, без особой надобности - Lua отлично. Но обойтись только ей - без шансов, а тем же Python какие-то шансы есть.

    ИМХО запев про Lua однозначен - она скриптует Neovim.


  1. nikolz
    29.05.2023 20:00
    +2

    Для разработки и отладки скриптов на Lua использую редактор SciTe, который написан на Lua. Есть API C for Lua, с помощью которого можно решить любые проблемы с быстродействием или с расширением функциональности. Lua это язык с динамической типизацией. Но есть очень интересные диалекты с включением статической типизации и параллельным вычислением на уровне jit компилятора. VM Lua примерно в 5 раз быстрее интерпретатора Python. Lua прекрасно работает на любом микропроцессоре и встраивается в любой SoC.


    1. Mingun
      29.05.2023 20:00
      +1

      Ну все же написан SciTE на плюсах, а Lua туда встроен.


      1. nikolz
        29.05.2023 20:00
        +1

        Спорить не буду, но рекомендую посмотреть исходники. Само приложение естественно написано на Си ( заголовочные файлы *.h), VMLua и все библиотеки - это тоже Си. Но это и так понятно, так как нет аппаратного процессора для данного языка. Он же скриптовый.

        Все настройки для различных языков, а также функции обработки текста реализованы на луа.

        Кроме того, в этом редакторе легко подключить и LuaJIT.

        В результате легко тестировать скрипты в окне редактора.

        API C позволяет писать dll, встаривать их в Lua и отлаживать в этом редакторе.


    1. pvvv
      29.05.2023 20:00

      https://studio.zerobrane.com/

      с лайвкодингом и удалённой отладкой,

      в том числе для redbean (https://notebook.kulchenko.com/redbean/redbean-debugging-with-zerobrane-studio) который тоже можно упомянуть раз уж про вебфреймворки в статье вспомнили.


  1. AllexIn
    29.05.2023 20:00
    +7

    Нет нужды беспокоиться о float, int, usize

    Ага. Нет нужды беспокоиться... Но есть нюанс: number - это сразу два типа: float и int. В зависимости от контекста и операций они разные. И это ведет к неочевидным(хоть и не частым) проблемам.
    Честно говоря, лучше бы сделали для разных типа. Потому что сейчас выглядит так, что хотели сделать "как проще", а потом оказалось что так не работает и навешали костылей.


    1. novusnota Автор
      29.05.2023 20:00

      Да, действительно, только эти "костыли" всё же идут намного дальше, чем чинят такую мелкую проблему. Например, Nelua добавляет статическую типизацию, опциональную (!) сборку мусора и транспиляцию в C или напрямую компиляцию в машинный код.


    1. pvvv
      29.05.2023 20:00
      +1

      ну да, небольшие костыли, потому что приделывали опосля, изначально решив что 640кБ 53бит мантиссы double хватит для любого целого числа. как и битовых операций тоже когда-то там не было.

      ну хоть так.


  1. SerJook
    29.05.2023 20:00

    Я в своё время выбрал Squirrel, потому что он ближе по синтаксису к C/C++.


    1. novusnota Автор
      29.05.2023 20:00

      Присмотритесь к:

      1. Terra — низкоуровневый язык, встраивающийся в Lua и позволяющий легко взаимодействовать с C/C++, причём даже с дженериками и шаблонами последнего!

      2. Nelua – Lua-подобный язык с типами и опциональной (!) сборкой мусора, который транспилируется в C или напрямую компилируется в машинный код.


  1. Raidar
    29.05.2023 20:00
    +3

    • Для разработки на Lua есть ZeroBrane Studio https://studio.zerobrane.com/.

    • Авторы Lua не гарантируют обратной совместимости.

    • На Lua можно писать макросы и скрипты для FAR Manager 3.0.


    1. domix32
      29.05.2023 20:00
      +1

      Ну, вообще до последней версии совместимость была, насколько мне известно. Последняя спека/релиз избавилась от некоторых странных поведений в угоду сломанной совместимости.


      1. novusnota Автор
        29.05.2023 20:00

        И да, и нет. Версии 5.2, 5.3, 5.4 все немного меняли API и слегка "надламывали" обратную совместимость, и только последние — 5.4.* решились на устранение фундаментальных странностей поведения языка :)

        К сожалению, например JavaScript так никак и не пофиксят в этом отношении.


  1. c00lc4t
    29.05.2023 20:00
    +2

    Порой приятно сидеть и читать что то такое простое и понятное, про лёгкий язык, который при этом может сделать многое. Спасибо за статью! Даже не смотря на краткость получилось крайне интересно


  1. shuhray
    29.05.2023 20:00
    +4

    Учил в своё время Lua, очень добрый и приятный язык, сделано в Бразилии. Но когда попробовал на нём рисовать, там есть только OpenGL2, а OpenGL3 уже нет. Потому что в OpenGL3 есть команды с двойными указателями ** и даже LuaJIT не может их понять (с одной звёздочкой может, в Lua вообще нет указателей, но LuaJIT позволяет вставлять в Lua кусочки кода на C). А так, гораздо приятнее, чем Питон и Яваскрипт. Lua, кстати, придумана (она женского рода, Lua значит "Луна") на год раньше Яваскрипта. В былые времена несколько раз слышал от разработчиков на Яваскрипт "как хорошо было бы, если бы сразу выбрали Lua вместо Яваскрипт!" Яваскрипт был сделан на коленке за два дня (как рассказывал его разработчик), что поначалу очень чувствовалось (сейчас его, кажется, доработали)


    1. playermet
      29.05.2023 20:00
      +2

      Потому что в OpenGL3 есть команды с двойными указателями ** и даже LuaJIT не может их понять

      Вполне понимает. Пример из моих биндингов для sqlite:

      -- модуль биндинга
      ...
      ffi.cdef [[
        int sqlite3_open(const char*, sqlite3**);
        ...
      ]]
      ...
      function funcs.open(filename)
        local db_p = ffi.new('sqlite3*[1]')
        local code = clib.sqlite3_open(filename, db_p)
        return code, db_p[0]
      end
      ...
      
      -- использование
      local sqlite = require 'sqlite3' ('sqlite3')
      local SQLITE = sqlite.const
      
      local code, db = sqlite.open(':memory:')
      ...


      1. novusnota Автор
        29.05.2023 20:00

        Очень показательный пример в свете удобства C FFI в Lua, спасибо, что делитесь!


        1. playermet
          29.05.2023 20:00
          +1

          Да не за что. Если интересует более полная версия, то можно посмотреть код на github для luajit-sqlite, luajit-tcc, luajit-glfw. У последних двух есть минимальный readme, и они в принципе рабочие и актуальные, не смотря на долгое отсутствие обновлений.

          Эти биндинги создавались частично в автоматизированном режиме с помощью скрипта на том же luajit. Нужные определения из C копировались в cdef, потом используя немного магии интроспекции прямо из под капота luajit'а извлекался список определений, и на его основе генерировался текст функций для всех не слишком сложных случаев. А уже потом я вручную допиливал где требуется более сложная логика.


  1. playermet
    29.05.2023 20:00
    +1

    А еще для Lua есть простенький аналог nodejs - luvit. Позволяет быстро писать простенькие серверные приложения:

    local http = require('http')
    
    http.createServer(function (req, res)
      local body = "Hello world\n"
      res:setHeader("Content-Type", "text/plain")
      res:setHeader("Content-Length", #body)
      res:finish(body)
    end):listen(1337, '127.0.0.1')
    
    print('Server running at http://127.0.0.1:1337/')

    Вместе с ним идет менеджер зависимостей, который дополнительно умеет упаковать среду выполения, скрипты, и ассеты (в т.ч. библиотеки) в один единственный исполняемый файл.

    Для разработки использую ZeroBrane (luacheck встроен), Sublime Text 4 с плагинами LSP + LSP-Lua (оба есть в packagecontrol).


  1. kovserg
    29.05.2023 20:00
    +1

    Нет нужды беспокоиться о float, int, usize

    Вот тут враньё. Очень даже стоит беспокоится. Т.к. в lua используется для представления числа или int64 или double. И когда используется int64 переполнения ведут себя как модульная арифметика по модулю 2^64, а когда double нет.


    x=1<<63 print(x) x=x*2 print(x)

    -9223372036854775808
    0

    ps: В отличии от питона lua можно собрать C компилятором под любую платформу например под dos


  1. max_dark
    29.05.2023 20:00
    +1

    У нас примерно миллион строк на Lua + миллион строк C++(либы + биндинги либ в Луа)

    И это боль - отсутствуют нормальные инструменты для поддержки подобного количества кода на Lua(частично скрашивает плагин EmmyLua для IDE от JetBrains, но там есть свои проблемы)

    Многие ошибки всплывают только у клиентов(в основном очепятки, nil-ы и подобное).

    Исправление одной ошибки занимает от суток до бесконечности.

    Не используйте Lua как основной язык - максимум длины для Lua-скрипта - строк 50(ИМХО)

    Я устал от Lua.


    1. alhimik45
      29.05.2023 20:00

      миллион строк на Lua + миллион строк C++

      А как так получилось? Прикрутили Lua для небольшого скриптинга, но это вышло из-под контроля и на нём стали целые фичи хреначить?


      1. max_dark
        29.05.2023 20:00
        +1

        Да, примерно так и было.


    1. Arenoros
      29.05.2023 20:00

      ну для visual studio есть отличный плагин для отладки lua(LuaDkmDebugger), который позволяет и точки останова делать и смотреть локальные параметры почти так же как если это был бы код на C++, но согласен что тонны кода на скриптовых языках это боль


  1. semennikov
    29.05.2023 20:00

    С моей точки зрения это очень удобный язык для управления железом, я выпускаю станки с ЧПУ со своей стойкой, и на LUA организован один из самых больших плюсов нашей стойки - интерпретатор G-кодов. Дело в том, что каждый производитель стоек дает свой набор G-кодов, и пользователь станков сразу привязан к производителю стоек, так как у него накапливается большой архив программ обработки именно для этой стойки, и когда он будет приобретать новый станок ему будет нужна именно такая стойка. А мы на LUA написали транслятор который программу для любой стойки переводит в программу для любой другой стойки


  1. selyutind
    29.05.2023 20:00

    По моим впечатлениям язык действительно очень легкий для освоения, при наличии опыта с другими ЯП втягиваешься в разработку «с колёс». Из недостатков — дебаг приложения и набор сторонних библиотек и фреймворков. Например, с взаимодействием с Kafka было немало трудностей.


  1. justoF
    29.05.2023 20:00

    Не так давно переписали наше платежное emv-kernel в новую архитектуру, как раз с использованием LUA

    https://mst-company.ru/blog/u-nas-novoe-emv-yadro