Lua ( / ˈl uːə / LOO -ə ; от португальского : lua [ˈlu(w)ɐ] означает луна ) — это лёгкий , высокоуровневый , многопарадигмальный язык программирования , разработанный в основном для встроенного использования в приложениях. [3] Lua — кроссплатформенное программное обеспечение , поскольку интерпретатор скомпилированного байт-кода написан на ANSI C , [4] и Lua имеет относительно простой интерфейс программирования приложений на языке C ( API ) для встраивания его в приложения. [ 5 ]
Lua возник в 1993 году как язык для расширения программных приложений , чтобы удовлетворить растущий спрос на настройку в то время. Он предоставлял основные возможности большинства процедурных языков программирования , но более сложные или предметно-специфичные функции не были включены; вместо этого он включал механизмы для расширения языка, позволяя программистам реализовывать такие функции. Поскольку Lua был задуман как общий встраиваемый язык расширения, проектировщики Lua сосредоточились на улучшении его скорости , переносимости , расширяемости и простоты использования при разработке.
Lua был создан в 1993 году Роберто Иерусалимши , Луисом Энрике де Фигейреду и Вальдемаром Селесом, членами Группы технологий компьютерной графики (Tecgraf) в Папском католическом университете Рио-де-Жанейро в Бразилии .
С 1977 по 1992 год Бразилия проводила политику жестких торговых барьеров (называемых рыночным резервом) для компьютерного оборудования и программного обеспечения , полагая, что Бразилия может и должна производить свое собственное оборудование и программное обеспечение. В этом климате клиенты Tecgraf не могли себе позволить, ни политически, ни финансово, покупать индивидуальное программное обеспечение из-за рубежа; в рамках рыночного резерва клиентам пришлось бы пройти сложный бюрократический процесс, чтобы доказать, что их потребности не могут быть удовлетворены бразильскими компаниями. Эти причины заставили Tecgraf внедрить основные необходимые инструменты с нуля. [6]
Предшественниками Lua были языки описания/конфигурирования данных Simple Object Language (SOL) и язык ввода данных (DEL). [7] Они были независимо разработаны в Tecgraf в 1992–1993 годах для добавления некоторой гибкости в два разных проекта (оба были интерактивными графическими программами для инженерных приложений в компании Petrobras ). В SOL и DEL отсутствовали какие-либо структуры управления потоком, и Petrobras чувствовала растущую потребность в добавлении к ним полной программной мощности.
В книге «Эволюция Lua » авторы языка писали: [6]
В 1993 году единственным реальным претендентом был Tcl , который был явно разработан для встраивания в приложения. Однако Tcl имел незнакомый синтаксис, не предлагал хорошей поддержки для описания данных и работал только на платформах Unix. Мы не рассматривали LISP или Scheme из-за их недружелюбного синтаксиса. Python все еще находился в зачаточном состоянии. В свободной, самодельной атмосфере, которая тогда царила в Tecgraf, было вполне естественно, что мы должны были попытаться разработать свой собственный язык сценариев... Поскольку многие потенциальные пользователи языка не были профессиональными программистами, язык должен был избегать криптического синтаксиса и семантики. Реализация нового языка должна была быть высокопереносимой, поскольку клиенты Tecgraf имели очень разнообразный набор компьютерных платформ. Наконец, поскольку мы ожидали, что другим продуктам Tecgraf также потребуется встраивать язык сценариев, новый язык должен был следовать примеру SOL и предоставляться в виде библиотеки с API на языке C.
Lua 1.0 был разработан таким образом, что его конструкторы объектов, которые тогда немного отличались от текущего легкого и гибкого стиля, включали синтаксис описания данных SOL (отсюда и название Lua: Sol означает «Солнце» на португальском языке, а Lua означает «Луна»). Синтаксис Lua для управляющих структур был в основном заимствован из Modula ( if
, while
, repeat
/ until
), но также подвергся влиянию CLU (множественные присваивания и множественные возвраты из вызовов функций, как более простая альтернатива ссылочным параметрам или явным указателям ), C++ («изящная идея разрешить объявлять локальную переменную только там, где она нам нужна» [6] ), SNOBOL и AWK ( ассоциативные массивы ). В статье, опубликованной в журнале Dr. Dobb's Journal , создатели Lua также заявляют, что LISP и Scheme с их единым, вездесущим механизмом структур данных ( список ) оказали большое влияние на их решение разработать таблицу как основную структуру данных Lua. [8]
Семантика Lua со временем все больше подвергалась влиянию Scheme, [6] особенно с введением анонимных функций и полной лексической области видимости . Несколько функций были добавлены в новых версиях Lua.
Версии Lua до версии 5.0 выпускались под лицензией, похожей на лицензию BSD . Начиная с версии 5.0, Lua лицензируется под лицензией MIT . Обе являются разрешительными лицензиями свободного ПО и практически идентичны.
Lua обычно описывается как « мультипарадигмальный » язык, предоставляющий небольшой набор общих функций, которые могут быть расширены для решения различных типов задач. Lua не содержит явной поддержки наследования , но позволяет реализовать его с помощью метатаблиц. Аналогично, Lua позволяет программистам реализовывать пространства имен , классы и другие связанные функции с помощью своей реализации с одной таблицей; функции первого класса позволяют использовать многие методы функционального программирования , а полная лексическая область видимости позволяет скрывать детальную информацию для обеспечения принципа наименьших привилегий .
В целом, Lua стремится предоставлять простые, гибкие метафункции , которые могут быть расширены по мере необходимости, а не предоставлять набор функций, специфичный для одной парадигмы программирования. В результате базовый язык легкий ; полный справочный интерпретатор занимает всего около 247 кБ в скомпилированном виде [4] и легко адаптируется к широкому спектру приложений.
Как динамически типизированный язык, предназначенный для использования в качестве языка расширений или языка сценариев , Lua достаточно компактен, чтобы поместиться на различных хост-платформах. Он поддерживает только небольшое количество атомарных структур данных, таких как логические значения, числа ( по умолчанию числа с плавающей точкой двойной точности и 64-битные целые числа ) и строки . Типичные структуры данных, такие как массивы , множества , списки и записи, могут быть представлены с помощью единственной собственной структуры данных Lua — таблицы, которая по сути является гетерогенным ассоциативным массивом .
Lua реализует небольшой набор расширенных функций, таких как функции первого класса , сборка мусора , замыкания , правильные хвостовые вызовы , приведение (автоматическое преобразование между строковыми и числовыми значениями во время выполнения), сопрограммы (кооперативная многозадачность) и динамическая загрузка модулей .
Классическую программу «Hello, World!» можно записать следующим образом, с круглыми скобками или без них: [9] [a]
печать ( "Привет, мир!" )
распечатать "Привет, мир!"
Комментарий в Lua начинается с двойного дефиса и продолжается до конца строки, подобно Ada , Eiffel , Haskell , SQL и VHDL . Многострочные строки и комментарии помечаются двойными квадратными скобками.
-- Однострочный комментарий --[[ Многострочный комментарий --]]
Функция факториала реализована в этом примере:
функция факториал ( n ) локальный x = 1 для i = 2 , n сделать x = x * i конец вернуть x конец
Lua имеет один тип условной проверки: if then end
с необязательными конструкциями else
и elseif then
конструкциями управления выполнением.
Для общего if then end
утверждения требуются все три ключевых слова:
если условие то --конец тела оператора
Ключевое else
слово может быть добавлено с сопровождающим блоком операторов для управления выполнением, когда if
условие оценивается как false
:
если условие то -- тело оператора иначе -- тело оператора конец
Выполнение также можно контролировать в соответствии с несколькими условиями, используя elseif then
ключевые слова:
если условие то -- тело оператора elseif условие то -- тело оператора else -- необязательно --необязательно по умолчанию тело оператора конец
Lua имеет четыре типа условных циклов: while
цикл , repeat
цикл (похожий на do while
цикл ), числовой for
цикл и общий for
цикл.
--условие = истиннов то время как условие do --statements endповторить --statements до тех пор, пока условиеfor i = first , last , delta do --delta может быть отрицательным, что позволяет циклу for вести отсчет в обратном или прямом направлении --statements --example: print(i) end
Этот общий for
цикл будет проходить по таблице, _G
используя стандартную функцию итератора pairs
, пока не вернет nil
:
для ключа , значения в парах ( _G ) сделать печать ( ключ , значение ) конец
Циклы также могут быть вложенными (помещаться внутрь другого цикла).
локальная сетка = { { 11 , 12 , 13 }, { 21 , 22 , 23 }, { 31 , 32 , 33 } }для y , строка в парах ( сетка ) сделать для x , значение в парах ( строка ) сделать печать ( x , y , значение ) конец конец
Обработка функций в Lua как значений первого класса показана в следующем примере, где поведение функции печати изменено:
do local oldprint = print -- Сохранение текущей функции печати как oldprint function print ( s ) --[[ Переопределение функции печати. Обычная функция печати по-прежнему может использоваться через oldprint. Новая имеет только один аргумент.]] oldprint ( s == "foo" and "bar" or s ) end end
Все будущие вызовы print
теперь будут направляться через новую функцию, и из-за лексической области видимости Lua старая функция печати будет доступна только новой, измененной функции печати.
Lua также поддерживает замыкания , как показано ниже:
function addto ( x ) -- Возвращает новую функцию, которая добавляет x к аргументу return function ( y ) --[[ Когда мы ссылаемся на переменную x, которая находится за пределами текущей области видимости и время жизни которой будет короче, чем у этой анонимной функции, Lua создает замыкание.]] return x + y end end fourplus = addto ( 4 ) print ( fourplus ( 3 )) -- Печатает 7--Этого также можно добиться, вызвав функцию следующим образом: print ( addto ( 4 )( 3 )) --[[ Это происходит потому, что мы вызываем возвращаемую функцию из 'addto(4)' с аргументом '3' напрямую. Это также помогает снизить стоимость данных и повысить производительность при итеративном вызове.]]
Новое замыкание для переменной x
создается каждый раз, когда addto
вызывается, так что каждая новая возвращаемая анонимная функция всегда будет иметь доступ к своему собственному x
параметру. Замыкание управляется сборщиком мусора Lua, как и любой другой объект.
Таблицы являются наиболее важными структурами данных (и, по замыслу, единственным встроенным составным типом данных ) в Lua и являются основой всех типов, создаваемых пользователем. Они представляют собой ассоциативные массивы с добавлением автоматического числового ключа и специального синтаксиса.
Таблица представляет собой набор пар ключей и данных, где данные ссылаются на ключ; другими словами, это хешированный гетерогенный ассоциативный массив.
Таблицы создаются с использованием {}
синтаксиса конструктора.
a_table = {} — Создает новую пустую таблицу
Таблицы всегда передаются по ссылке (см . Вызов путем совместного использования ).
Ключ (индекс) может быть любым значением, кроме nil
NaN , включая функции.
a_table = { x = 10 } — Создает новую таблицу с одной записью, сопоставляющей «x» с числом 10. print ( a_table [ "x" ]) — Печатает значение, связанное со строковым ключом, в данном случае 10. b_table = a_table b_table [ "x" ] = 20 — Значение в таблице было изменено на 20. print ( b_table [ "x" ]) — Печатает 20. print ( a_table [ "x" ]) — Также печатает 20, поскольку a_table и b_table ссылаются на одну и ту же таблицу.
Таблица часто используется как структура (или запись ) с использованием строк в качестве ключей. Поскольку такое использование очень распространено, Lua имеет специальный синтаксис для доступа к таким полям. [11]
point = { x = 10 , y = 20 } -- Создать новую таблицу print ( point [ "x" ]) -- Выводит 10 print ( point . x ) -- Имеет точно такое же значение, как строка выше. Более простая для чтения точечная нотация — это просто синтаксический сахар.
Используя таблицу для хранения связанных функций, ее можно использовать в качестве пространства имен.
Точка = {}Точка . новая = функция ( x , y ) return { x = x , y = y } -- return {["x"] = x, ["y"] = y} endТочка.set_x = функция ( точка , x ) точка.x = x -- точка [ " x"] = x; конец
Таблицам автоматически назначается числовой ключ, что позволяет использовать их как тип данных массива . Первый автоматический индекс равен 1, а не 0, как во многих других языках программирования (хотя явный индекс 0 допускается).
Числовой ключ 1
отличается от строкового ключа "1"
.
array = { "a" , "b" , "c" , "d" } -- Индексы назначаются автоматически. print ( array [ 2 ]) -- Выводит "b". Автоматическая индексация в Lua начинается с 1. print ( # array ) -- Выводит 4. # — оператор длины для таблиц и строк. array [ 0 ] = "z" -- Ноль — допустимый индекс. print ( # array ) -- По-прежнему выводит 4, так как массивы Lua начинаются с 1.
Длина таблицы t
определяется как любой целочисленный индекс, n
такой что t[n]
не является nil
и t[n+1]
является nil
; более того, если t[1]
является nil
, n
может быть равен нулю. Для обычного массива с ненулевыми значениями от 1 до заданного n
его длина равна в точности n
, индексу его последнего значения. Если массив имеет «дыры» (то есть нулевые значения между другими ненулевыми значениями), то #t
может быть любым из индексов, который непосредственно предшествует nil
значению (то есть он может считать любое такое нулевое значение концом массива). [12]
ExampleTable = { { 1 , 2 , 3 , 4 }, { 5 , 6 , 7 , 8 } } print ( ExampleTable [ 1 ][ 3 ]) -- Печатает "3" print ( ExampleTable [ 2 ][ 4 ]) -- Печатает "8"
Таблица может быть массивом объектов.
function Point ( x , y ) — конструктор объекта «Точка» return { x = x , y = y } — создает и возвращает новый объект (таблицу) end array = { Point ( 10 , 20 ), Point ( 30 , 40 ), Point ( 50 , 60 ) } — создает массив точек — array = { { x = 10, y = 20}, { x = 30, y = 40}, { x = 50, y = 60} }; print ( array [ 2 ] .y ) — печатает 40
Использование хэш-карты для эмуляции массива обычно медленнее, чем использование реального массива; однако таблицы Lua оптимизированы для использования в качестве массивов, чтобы помочь избежать этой проблемы. [13]
Расширяемая семантика является ключевой особенностью Lua, а концепция метатаблиц обеспечивает мощную настройку таблиц. Следующий пример демонстрирует "бесконечную" таблицу. Для любого n
, fibs[n]
даст n
-ое число Фибоначчи с использованием динамического программирования и мемоизации .
fibs = { 1 , 1 } -- Начальные значения для fibs[1] и fibs[2]. setmetatable ( fibs , { __index = function ( values , n ) --[[__index — это функция, предопределенная Lua, она вызывается, если ключ "n" не существует.]] values [ n ] = values [ n - 1 ] + values [ n - 2 ] -- Вычислить и сохранить fibs[n]. return values [ n ] end })
Хотя Lua не имеет встроенной концепции классов , объектно-ориентированное программирование можно эмулировать с помощью функций и таблиц. Объект формируется путем помещения методов и полей в таблицу. Наследование (как одиночное, так и множественное) можно реализовать с помощью метатаблиц, делегируя несуществующие методы и поля родительскому объекту.
В этих методах нет такого понятия, как «класс»; вместо этого используются прототипы , похожие на Self или JavaScript . Новые объекты создаются либо с помощью фабричного метода (который создает новые объекты с нуля), либо путем клонирования существующего объекта.
Создание базового векторного объекта:
локальный Вектор = {} локальный VectorMeta = { __index = Вектор }function Vector.new ( x , y , z ) — конструктор return setmetatable ( { x = x , y = y , z = z } , VectorMeta ) end функция Вектор.величина ( self ) — Другой метод return math.sqrt ( self.x ^ 2 + self.y ^ 2 + self.z ^ 2 ) end local vec = Vector.new ( 0,1,0 ) — Создать вектор print ( vec.Magnitude ( vec ) ) — Вызвать метод (выход: 1) print ( vec.x ) — Получить доступ к переменной-члену (выход : 0 )
Здесь, setmetatable
говорит Lua искать элемент в Vector
таблице, если он отсутствует в vec
таблице. , что эквивалентно , сначала ищет элемент в таблице. Таблица не содержит элемента, но ее метатаблица делегирует таблице задачу для элемента , если он не найден в таблице.vec.magnitude
vec["magnitude"]
vec
magnitude
vec
magnitude
Vector
magnitude
vec
Lua предоставляет некоторый синтаксический сахар для облегчения объектной ориентации. Чтобы объявить функции-члены внутри таблицы прототипов, можно использовать , что эквивалентно . Вызов методов класса также использует двоеточие: эквивалентно .function table:func(args)
function table.func(self, args)
object:func(args)
object.func(object, args)
Имея это в виду, вот соответствующий класс с :
синтаксическим сахаром:
локальный Вектор = {} Вектор . __index = Векторfunction Vector : new ( x , y , z ) -- Конструктор -- Поскольку определение функции использует двоеточие, -- ее первым аргументом является "self", что ссылается на "Vector" return setmetatable ({ x = x , y = y , z = z }, self ) endfunction Vector : magnetic ( ) -- Другой метод -- Ссылка на неявный объект с помощью self return math.sqrt ( self.x ^ 2 + self.y ^ 2 + self.z ^ 2 ) end local vec = Vector : new ( 0 , 1 , 0 ) -- Создать вектор print ( vec : magnetic ()) -- Вызвать метод (выход: 1) print ( vec . x ) -- Доступ к переменной-члену (выход: 0)
Lua поддерживает использование метатаблиц для наследования классов Lua. [14] В этом примере мы разрешаем векторам умножать свои значения на константу в производном классе.
локальный Вектор = {} Вектор . __index = Векторfunction Vector : new ( x , y , z ) -- Конструктор -- Здесь self ссылается на любой "новый" -- метод класса, который мы вызываем. В производном классе self будет -- производным классом; в классе Vector self -- будет Vector return setmetatable ({ x = x , y = y , z = z }, self ) endfunction Vector : magnetic ( ) -- Другой метод -- Ссылка на неявный объект с помощью self return math.sqrt ( self.x ^ 2 + self.y ^ 2 + self.z ^ 2 ) end -- Пример наследования классов local VectorMult = {} VectorMult . __index = VectorMult setmetatable ( VectorMult , Vector ) -- Сделать VectorMult дочерним классом Vectorфункция VectorMult : умножить ( значение ) self.x = self.x * значение self.y = self.y * значение self.z = self.z * значение return self end local vec = VectorMult : new ( 0 , 1 , 0 ) -- Создать вектор print ( vec : magnetic ()) -- Вызвать метод (выход: 1) print ( vec . y ) -- Доступ к переменной-члену (выход: 1) vec : multiply ( 2 ) -- Умножить все компоненты вектора на 2 print ( vec . y ) -- Повторный доступ к члену (выход: 2)
Lua также поддерживает множественное наследование ; __index
может быть либо функцией, либо таблицей. [15] Также может быть выполнена перегрузка операторов__add
; метатаблицы Lua могут иметь такие элементы , как __sub
и т. д. [16]
Программы Lua не интерпретируются напрямую из текстового файла Lua, а компилируются в байт-код, который затем запускается на виртуальной машине Lua (VM). Процесс компиляции обычно невидим для пользователя и выполняется во время выполнения , особенно когда используется компилятор JIT ( just-in-time compilation ), но его можно выполнять в автономном режиме, чтобы увеличить производительность загрузки или уменьшить объем памяти хост-среды, исключив компилятор. Байт-код Lua также может быть создан и выполнен из Lua, используя функцию dump
из библиотеки строк и load/loadstring/loadfile
функции. Lua версии 5.3.4 реализован примерно в 24 000 строк кода C. [3] [4]
Как и большинство ЦП, и в отличие от большинства виртуальных машин (которые основаны на стеке ), Lua VM основана на регистрах , и поэтому больше похожа на большинство аппаратных разработок. Архитектура регистров позволяет избежать избыточного копирования значений и уменьшает общее количество инструкций на функцию. Виртуальная машина Lua 5 является одной из первых чистых виртуальных машин на основе регистров, получивших широкое распространение. [ 17] Parrot и Android Dalvik — две другие известные виртуальные машины на основе регистров. Виртуальная машина PCScheme также была основана на регистрах. [18]
Этот пример представляет собой листинг байт-кода функции факториала, определенной выше (как показано компилятором luac
5.1): [19]
функция <factorial.lua:1,7> (9 инструкций, 36 байт по адресу 0x8063c60)1 параметр, 6 слотов, 0 верхних значений, 6 локальных переменных, 2 константы, 0 функций1 [2] ЗАГРУЗКА 1 -1 ; 12 [3] НАГРУЗКА 2 -2 ; 23 [3] ХОД 3 04 [3] НАГРУЗКА 4 -1 ; 15 [3] FORPREP 2 1 ; к 76 [4] МУЛЬ 1 1 57 [3] FORLOOP 2 -2 ; до 68 [6] ВОЗВРАТ 1 29 [7] ВОЗВРАТ 0 1
Lua предназначен для встраивания в другие приложения и предоставляет API C для этой цели. API делится на две части: ядро Lua и вспомогательную библиотеку Lua. [20] Дизайн API Lua устраняет необходимость ручного подсчета ссылок (управления) в коде C, в отличие от API Python . API, как и язык, минималистский. Расширенные функции предоставляются вспомогательной библиотекой, которая в основном состоит из макросов препроцессора , которые помогают со сложными операциями с таблицами.
API Lua C основано на стеке . Lua предоставляет функции для помещения и извлечения большинства простых типов данных C (целые числа, числа с плавающей точкой и т. д.) в стек и из него, а также функции для управления таблицами через стек. Стек Lua несколько отличается от традиционного стека; например, стек можно индексировать напрямую. Отрицательные индексы указывают смещения от вершины стека. Например, −1 — это вершина (последнее помещенное значение), тогда как положительные индексы указывают смещения от низа (старое значение). Маршалинг данных между функциями C и Lua также выполняется с использованием стека. Для вызова функции Lua аргументы помещаются в стек, а затем lua_call
используется для вызова фактической функции. При написании функции C для непосредственного вызова из Lua аргументы считываются из стека.
Вот пример вызова функции Lua из C:
#include <stdio.h> #include <lua.h> // Основная библиотека Lua (lua_*) #include <lauxlib.h> // Вспомогательная библиотека Lua (luaL_*) int main ( void ) { // создаем состояние Lua lua_State * L = luaL_newstate (); // загрузить и выполнить строку if ( luaL_dostring ( L , "function foo (x,y) return x+y end" )) { lua_close ( L ); return -1 ; } // помещаем значение глобальной переменной "foo" (функция, определенная выше) // в стек, за которым следуют целые числа 5 и 3 lua_getglobal ( L , "foo" ); lua_pushinteger ( L , 5 ); lua_pushinteger ( L , 3 ); lua_call ( L , 2 , 1 ); // вызываем функцию с двумя аргументами и одним возвращаемым значением printf ( "Result: %d \n " , lua_tointeger ( L , -1 )); // печатаем целочисленное значение элемента на вершине стека lua_pop ( L , 1 ); // возвращаем стек в исходное состояние lua_close ( L ); // закрываем состояние Lua return 0 ; }
Выполнение этого примера даст:
$ cc -o пример example.c -llua $ ./example Результат: 8
API C также предоставляет некоторые специальные таблицы, расположенные в различных "псевдоиндексах" в стеке Lua. В LUA_GLOBALSINDEX
версии до Lua 5.2 [21] находится таблица globals, _G
из Lua, которая является основным пространством имен . Также есть реестр, расположенный в, LUA_REGISTRYINDEX
где программы C могут хранить значения Lua для последующего извлечения.
Помимо стандартных библиотечных (основных) модулей, можно писать расширения с помощью API Lua. Модули расширения — это общие объекты , которые можно использовать для расширения функций интерпретатора, предоставляя собственные возможности скриптам Lua. Скрипты Lua могут загружать модули расширения с помощью require
, [20] точно так же, как модули, написанные на самом Lua, или с помощью package.loadlib
. [22] Когда библиотека C загружается через Lua, она ищет функцию и вызывает ее, которая действует как любая функция C, вызываемая из Lua, и обычно возвращает таблицу, заполненную методами. Растущий набор модулей, называемых камнями, доступен через систему управления пакетами LuaRocks , [23] в духе CPAN , RubyGems и Python eggs. Предварительно написанные привязки Lua существуют для большинства популярных языков программирования, включая другие языки сценариев. [24] Для C++ существует ряд подходов на основе шаблонов и несколько автоматических генераторов привязок.require('foo')
luaopen_foo
В разработке видеоигр Lua широко используется в качестве языка сценариев , в основном из-за его воспринимаемой простоты встраивания, быстрого выполнения и короткой кривой обучения . [25] Известные игры, которые используют Lua, включают Roblox , [26] Garry's Mod , World of Warcraft , Payday 2 , Phantasy Star Online 2 , Dota 2 , Crysis , [27] и многие другие. Некоторые игры, которые изначально не поддерживают программирование или сценарии Lua, имеют эту функцию, добавленную модами, как ComputerCraft для Minecraft . Кроме того, Lua используется в программном обеспечении, не относящемся к видеоиграм, таком как Adobe Lightroom , Moho , iClone , Aerospike и некотором системном программном обеспечении в FreeBSD и NetBSD , а также используется в качестве языка сценариев шаблонов в MediaWiki с использованием расширения Scribunto. [28]
В 2003 году опрос, проведенный GameDev.net, показал, что Lua является самым популярным языком сценариев для программирования игр. [29] 12 января 2012 года Lua был объявлен победителем премии Front Line Award 2011 от журнала Game Developer в категории «Инструменты программирования». [30]
Многие неигровые приложения также используют Lua для расширения, например , LuaTeX (реализация языка набора текста TeX ), Redis ( база данных «ключ-значение») , ScyllaDB ( хранилище с широкими столбцами ), Neovim (текстовый редактор), Nginx ( веб-сервер ) и Wireshark (анализатор сетевых пакетов).
Благодаря расширению Scribunto, Lua доступен как серверный язык сценариев в программном обеспечении MediaWiki , которое управляет Wikipedia и другими вики. [31] Среди его применений — обеспечение интеграции данных из Wikidata в статьи, [32] и поддержка автоматизированной системы taxobox .
do
and end
(или {
and ) для разделения }
разделов кода он использует переносы строк и стиль отступов . [33] [34] [35] Известным применением MoonScript является сайт распространения видеоигр Itch.io.Кроме того, сообщество пользователей Lua предоставляет некоторые мощные патчи поверх эталонной реализации C. [44]
{{cite book}}
: |work=
проигнорировано ( помощь ){{cite web}}
: CS1 maint: бот: исходный статус URL неизвестен ( ссылка )Все это побудило нас начать переделывать Lua 5.1, с которого мы начинали, в новый производный язык, который мы называем Luau. Мы сосредоточены на том, чтобы сделать язык более производительным и многофункциональным, а также упростить написание надежного кода с помощью комбинации линтинга и проверки типов с использованием постепенной системы типов.