- PVSM.RU - https://www.pvsm.ru -
Lua — это лёгкий, быстрый и гибкий скриптовый язык, который появился в 1993 году. Он написан на C и чаще всего используется не как самостоятельный язык, а как встраиваемый инструмент для других приложений.
Если вы играли в World of Warcraft и устанавливали аддоны, вы уже сталкивались с Lua. Redis исполняет Lua-скрипты внутри себя. Nginx использует его для обработки HTTP-запросов. В NeoVim плагины тоже можно писать на Lua. Короче говоря — язык не из популярных топов, но крайне полезен и встраиваем во многие инфраструктурные решения.
Начнём с классики:
print("Hello, World!")
Синтаксис Lua немного напоминает Pascal и Python: конструкции завершаются end, типы выводятся автоматически, всё просто и компактно — идеально для скриптов и прототипов.
В языке есть локальные и глобальные переменные:
Локальные объявляются через local и живут только в пределах текущего блока.
Глобальные — по умолчанию. Они сохраняются в специальной таблице _G, доступной из любого куска кода, работающего в той же среде выполнения.
Пример чуть более практичный — задача из Advent of Code 2022, день 1 [1]:
Найти максимальную сумму чисел, сгруппированных по блокам, разделённым пустыми строками.
local max, current = 0, 0
for line in io.lines("input.txt") do
if line == "" then
if current > max then
max = current
end
current = 0
else
current = current + tonumber(line)
end
end
if current > max then
max = current
end
print(max)
В Lua всего восемь базовых типов:
number, string, boolean, nil, function, table, thread, userdata
number объединяет и целые, и дробные числа.
string — обычные строки, являются иммутабельными.
nil — Null, Nil, None называй как хочешь.
function — функции — это значения первого класса: их можно присваивать переменным, передавать как аргументы и возвращать из других функций.
table — универсальная структура данных: массив (индексируются с 1), словарь и объект — всё в одном.
thread — корутины.
userdata — интерфейс для взаимодействия с C-данными.
Типизация динамическая и слабая: переменные могут менять тип на лету, а Lua часто пытается «угадать» вашу задумку. Например, строку "42" можно неявно превратить в число. А если все таки хочется явного приведения типов, то существуют встроенные функции для такого: например tonumber(n) или tostring(s).
Lua удобно встроить в любую программу на C или даже Go. Интерпретатор предоставляет простой C API [2], через который можно выполнять скрипты, обмениваться данными и расширять язык новыми функциями.
Предположим есть Lua-файл fib5.lua который считает число Фибоначчи и возвращает результат для числа 5.
function fib(n)
local fib = {1, 1}
for i = 3,n,1 do
fib[#fib+1] = fib[#fib] + fib[#fib-1]
end
return fib[n]
end
return fib(5)
Программа на Go:
Я буду использовать пакет github.com/yuin/gopher-lua [3] который предоставляет простой интерфейс взаимодействия, но при желании можно обойтись и без лишних зависимостей с помощью CGO.
package main
import (
"fmt"
lua "github.com/yuin/gopher-lua"
)
func main() {
var l *lua.LState = lua.NewState()
defer l.Close()
if err := l.DoFile("fib5.lua"); err != nil {
panic(err)
}
// достаем результат выполнения с вершины стэка
result := l.Get(-1) // result типа lua.LValue
// и очищаем его
l.Pop(1)
fmt.Printf("result: %dn", result) // result: 5
}
Eсли мы захотим заново выполнить подсчет, то нам не надо заново загружать файл, функция fib(n) уже лежит в глобальных переменных нашего l *lua.LState Нужно лишь достать её оттуда и положить на стэк вместе с аргументами, а затем вызвать l.Call(nargs, nret) для получения результата.
...
//складываем на стэк функцию из глобальных переменных
l.Push(l.GetGlobal("fib")) // stack: function "fib"
//складываем на стэк аргумент функции
l.Push(lua.LNumber(15)) // stack: function "fib", 15
// l.Call забирает из стэка функцию и 1 аргумент, и складывает обратно 1 результат
l.Call(1, 1) // stack: 610
result = l.Get(-1) // stack: 610
l.Pop(1) // stack:
fmt.Printf("result: %dn", result) //result: 610
Небольшое уточнение: не примитивные типы используемые в 2 языках сильно отличаются (особенно массивы), поэтому часто требуется нетривиальные преобразования чтобы получить нормальный результат.
Lua активно применяется в реальных проектах:
World of Warcraft — аддоны и интерфейс.
Redis — атомарные операции в скриптах.
Nginx — модуль ngx_http_lua_module.
NeoVim — современный API для плагинов.
Игровые движки — Defold, Pico-8, Love2D и другие.
Lua — не универсальный язык на все случаи жизни. Но если вы:
пишете backend на Nginx или Redis,
работаете с NeoVim и хотите делать плагины,
или просто хотите встроить скриптовый язык в своё приложение,
... то Lua — это идеальный инструмент. Он маленький, быстрый и гибкий. И к тому же — приятно удивляет своей лаконичностью.
Автор: minmax1996
Источник [4]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/golang/416086
Ссылки в тексте:
[1] Advent of Code 2022, день 1: https://adventofcode.com/2022/day/1
[2] простой C API: https://www.lua.org/pil/24.html
[3] github.com/yuin/gopher-lua: https://github.com/yuin/gopher-lua
[4] Источник: https://habr.com/ru/articles/898828/?utm_source=habrahabr&utm_medium=rss&utm_campaign=898828
Нажмите здесь для печати.