LuaНачало работы с Lua


замечания

Логотип Lua

Lua - минималистичный, легкий и встраиваемый язык сценариев. Он разрабатывается, внедряется и поддерживается командой в PUC-Rio , Папском католическом университете Рио-де-Жанейро в Бразилии. Список рассылки открыт для участия.

Обычные прецеденты для Lua включают в себя скриптовые видеоигры, расширение приложений с помощью плагинов и конфигов, перенос некоторых бизнес-логик высокого уровня или просто внедрение в такие устройства, как телевизоры, автомобили и т. Д.

Для высокопроизводительных задач существует независимая реализация с использованием доступного во времени компилятора LuaJIT .

Версии

Версия Заметки Дата выхода
1,0 Первоначальный, непубличный выпуск. 1993-07-28
1,1 Первый публичный выпуск. В документе описывается это. 1994-07-08
2,1 Начиная с Lua 2.1, Lua стал свободно доступным для всех целей, включая коммерческое использование. Журнал, описывающий его. 1995-02-07
2,2 Длинные строки, интерфейс отладки, лучшие трассировки стека 1995-11-28
2,4 Внешний компилятор luac 1996-05-14
2.5 Совмещение шаблонов и функции vararg. 1996-11-19
3.0 Введена auxlib, библиотека для помощи в написании библиотек Lua 1997-07-01
3,1 Анонимные функции и закрытие функций с помощью «upvalues». 1998-07-11
3,2 Библиотека отладки и новые функции таблицы 1999-07-08
3.2.2 2000-02-22
4,0 Несколько состояний, «для» операторов, API revamp. 2000-11-06
4.0.1 2002-07-04
5.0 Coroutines, metatables, полный лексический охват, tail calls, booleans переходят на лицензию MIT. 2003-04-11
5.0.3 2006-06-26
5,1 Обновление системы модулей, инкрементный сборщик мусора, метаданные для всех типов, luaconf.h revamp, полностью реентеративный парсер, вариативные аргументы. 2006-02-21
5.1.5 2012-02-17
5,2 Экстренный сборщик мусора, goto, финализаторы для столов. 2011-12-16
5.2.4 2015-03-07
5,3 Базовая поддержка UTF-8, побитовые операции, 32/64-битные целые числа. 2015-01-12
5.3.4 Последняя версия. 2017-01-12

Комментарии

Однострочные комментарии в Lua начинаются с -- и продолжаются до конца строки:

-- this is single line comment
-- need another line
-- huh?
 

Заблокировать комментарии начинаются с --[[ и заканчиваются с ]] :

--[[
    This is block comment.
    So, it can go on...
    and on...
    and on....
]]
 

Блочные комментарии используют тот же стиль разделителей, что и длинные строки; любое количество знаков равенства может быть добавлено между скобками, чтобы разграничить комментарий:

--[=[
    This is also a block comment
    We can include "]]" inside this comment
--]=]

--[==[
    This is also a block comment
    We can include "]=]" inside this comment
--]==]
 

Чистый трюк, чтобы прокомментировать фрагменты кода, состоит в том, чтобы окружить его --[[ и --]] :

--[[
    print'Lua is lovely'
--]]
 

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

---[[
    print'Lua is lovely'
--]]
 

Таким образом, последовательность -- в первой строке запускает однострочный комментарий, как и предыдущая строка, и оператор print не закомментирован.

Сделав еще один шаг, два блока кода могут быть настроены таким образом, что если первый блок будет закомментирован, второй не будет, и наоборот:

---[[
  print 'Lua is love'
--[=[]]
  print 'Lua is life'
--]=]
 

Чтобы активировать второй фрагмент при отключении первого фрагмента, удалите ведущий - в первой строке:

--[[
  print 'Lua is love'
--[=[]]
  print 'Lua is life'
--]=]
 

Выполнение программ Lua

Обычно Lua поставляется с двумя двоичными файлами:

  • lua - автономный интерпретатор и интерактивная оболочка
  • компилятор luac - байт-код

Допустим, у нас есть пример программы ( bottles_of_mate.lua ) следующим образом:

local string = require "string"    

function bottle_take(bottles_available)

    local count_str = "%d bottles of mate on the wall."
    local take_str = "Take one down, pass it around, " .. count_str
    local end_str = "Oh noes, " .. count_str
    local buy_str = "Get some from the store, " .. count_str
    local bottles_left = 0

    if bottles_available > 0 then
         print(string.format(count_str, bottles_available))
         bottles_left = bottles_available - 1
         print(string.format(take_str, bottles_left))
    else
        print(string.format(end_str, bottles_available))
        bottles_left = 99
        print(string.format(buy_str, bottles_left))
    end

    return bottles_left
end

local bottle_count = 99

while true do
    bottle_count = bottle_take(bottle_count)
end
 

Сама программа может быть запущена, выполнив следующую команду в своей оболочке:

$ lua bottles_of_mate.lua
 

Результат должен выглядеть следующим образом: бег в бесконечном цикле:

Get some from the store, 99 bottles of mate on the wall.
99 bottles of mate on the wall.
Take one down, pass it around, 98 bottles of mate on the wall.
98 bottles of mate on the wall.
Take one down, pass it around, 97 bottles of mate on the wall.
97 bottles of mate on the wall.
...
...
3 bottles of mate on the wall.
Take one down, pass it around, 2 bottles of mate on the wall.
2 bottles of mate on the wall.
Take one down, pass it around, 1 bottles of mate on the wall.
1 bottles of mate on the wall.
Take one down, pass it around, 0 bottles of mate on the wall.
Oh noes, 0 bottles of mate on the wall.
Get some from the store, 99 bottles of mate on the wall.
99 bottles of mate on the wall.
Take one down, pass it around, 98 bottles of mate on the wall.
...
 

Вы можете скомпилировать программу в байт-код Lua, выполнив следующую команду в своей оболочке:

$ luac bottles_of_mate.lua -o bottles_of_mate.luac
 

Также перечисление байт-кода доступно, выполнив следующие действия:

$ luac -l bottles_of_mate.lua


main <./bottles.lua:0,0> (13 instructions, 52 bytes at 0x101d530)
0+ params, 4 slots, 0 upvalues, 2 locals, 4 constants, 1 function
    1    [1]    GETGLOBAL    0 -1    ; require
    2    [1]    LOADK        1 -2    ; "string"
    3    [1]    CALL         0 2 2
    4    [22]    CLOSURE      1 0    ; 0x101d710
    5    [22]    MOVE         0 0
    6    [3]    SETGLOBAL    1 -3    ; bottle_take
    7    [24]    LOADK        1 -4    ; 99
    8    [27]    GETGLOBAL    2 -3    ; bottle_take
    9    [27]    MOVE         3 1
    10    [27]    CALL         2 2 2
    11    [27]    MOVE         1 2
    12    [27]    JMP          -5    ; to 8
    13    [28]    RETURN       0 1

function <./bottles.lua:3,22> (46 instructions, 184 bytes at 0x101d710)
1 param, 10 slots, 1 upvalue, 6 locals, 9 constants, 0 functions
    1    [5]    LOADK        1 -1    ; "%d bottles of mate on the wall."
    2    [6]    LOADK        2 -2    ; "Take one down, pass it around, "
    3    [6]    MOVE         3 1
    4    [6]    CONCAT       2 2 3
    5    [7]    LOADK        3 -3    ; "Oh noes, "
    6    [7]    MOVE         4 1
    7    [7]    CONCAT       3 3 4
    8    [8]    LOADK        4 -4    ; "Get some from the store, "
    9    [8]    MOVE         5 1
    10    [8]    CONCAT       4 4 5
    11    [9]    LOADK        5 -5    ; 0
    12    [11]    EQ           1 0 -5    ; - 0
    13    [11]    JMP          16    ; to 30
    14    [12]    GETGLOBAL    6 -6    ; print
    15    [12]    GETUPVAL     7 0    ; string
    16    [12]    GETTABLE     7 7 -7    ; "format"
    17    [12]    MOVE         8 1
    18    [12]    MOVE         9 0
    19    [12]    CALL         7 3 0
    20    [12]    CALL         6 0 1
    21    [13]    SUB          5 0 -8    ; - 1
    22    [14]    GETGLOBAL    6 -6    ; print
    23    [14]    GETUPVAL     7 0    ; string
    24    [14]    GETTABLE     7 7 -7    ; "format"
    25    [14]    MOVE         8 2
    26    [14]    MOVE         9 5
    27    [14]    CALL         7 3 0
    28    [14]    CALL         6 0 1
    29    [14]    JMP          15    ; to 45
    30    [16]    GETGLOBAL    6 -6    ; print
    31    [16]    GETUPVAL     7 0    ; string
    32    [16]    GETTABLE     7 7 -7    ; "format"
    33    [16]    MOVE         8 3
    34    [16]    MOVE         9 0
    35    [16]    CALL         7 3 0
    36    [16]    CALL         6 0 1
    37    [17]    LOADK        5 -9    ; 99
    38    [18]    GETGLOBAL    6 -6    ; print
    39    [18]    GETUPVAL     7 0    ; string
    40    [18]    GETTABLE     7 7 -7    ; "format"
    41    [18]    MOVE         8 4
    42    [18]    MOVE         9 5
    43    [18]    CALL         7 3 0
    44    [18]    CALL         6 0 1
    45    [21]    RETURN       5 2
    46    [22]    RETURN       0 1
 

Начиная

переменные

var = 50 -- a global variable
print(var) --> 50
do
  local var = 100 -- a local variable
  print(var) --> 100
end
print(var) --> 50
-- The global var (50) still exists 
-- The local var (100) has gone out of scope and can't be accessed any longer.
 

типы

num = 20 -- a number
num = 20.001 -- still a number
str = "zaldrizes buzdari iksos daor" -- a string
tab = {1, 2, 3} -- a table (these have their own category)
bool = true -- a boolean value
bool = false -- the only other boolean value
print(type(num)) --> 'number'
print(type(str)) --> 'string'
print(type(bool)) --> 'boolean'
type(type(num)) --> 'string'

-- Functions are a type too, and first-class values in Lua.
print(type(print)) --> prints 'function'
old_print = print
print = function (x) old_print "I'm ignoring the param you passed me!" end
old_print(type(print)) --> Still prints 'function' since it's still a function.
-- But we've (unhelpfully) redefined the behavior of print.
print("Hello, world!") --> prints "I'm ignoring the param you passed me!"
 

Специальный тип nil

Другой тип в Lua - nil . Единственное значение в nil типа является nil . nil существует, чтобы отличаться от всех других значений в Lua. Это своего рода неценовое значение.

print(foo) -- This prints nil since there's nothing stored in the variable 'foo'.
foo = 20
print(foo) -- Now this prints 20 since we've assigned 'foo' a value of 20.

-- We can also use `nil` to undefine a variable
foo = nil -- Here we set 'foo' to nil so that it can be garbage-collected.

if nil then print "nil" end --> (prints nothing)
-- Only false and nil are considered false; every other value is true.
if 0 then print "0" end --> 0
if "" then print "Empty string!" --> Empty string!
 

выражения

a = 3
b = a + 20 a = 2 print(b, a) -- hard to read, can also be written as
b = a + 20; a = 2; print(a, b) -- easier to read, ; are optional though
true and true --> returns true
true and 20 --> 20
false and 20 --> false
false or 20 --> 20
true or 20 --> true
tab or {}
  --> returns tab if it is defined
  --> returns {} if tab is undefined
  -- This is useful when we don't know if a variable exists
tab = tab or {} -- tab stays unchanged if it exists; tab becomes {} if it was previously nil.

a, b = 20, 30 -- this also works
a, b = b, a -- switches values
 

Определение функций

function name(parameter)
    return parameter
end
print(name(20)) --> 20
-- see function category for more information
name = function(parameter) return parameter end -- Same as above
 

булевы

Только false и nil оцениваются как false, все остальное, включая 0 а пустая строка оценивается как истина.

вывоз мусора

tab = {"lots", "of", "data"}
tab = nil; collectgarbage()
-- tab does no longer exist, and doesn't take up memory anymore.
 

таблицы

tab1 = {"a", "b", "c"}
tab2 = tab1
tab2[1] = "d"
print(tab1[1]) --> 'd' -- table values only store references.
--> assigning tables does not copy its content, only the reference.

tab2 = nil; collectgarbage()
print(tab1) --> (prints table address) -- tab1 still exists; it didn't get garbage-collected.

tab1 = nil; collectgarbage()
-- No more references. Now it should actually be gone from memory.
 

Это основы, но есть раздел о таблицах с дополнительной информацией.

условия

if (condition) then
    -- do something
elseif (other_condition) then
    -- do something else
else
    -- do something
end
 

для петель

Существует два типа цикла for в Lua: числовое значение for цикла и общий for цикла.

  • Цифры for цикла имеют следующий вид:

    for a=1, 10, 2 do -- for a starting at 1, ending at 10, in steps of 2
      print(a) --> 1, 3, 5, 7, 9
    end
     

    Третье выражение в числовой for цикла представляет собой этап , по которому цикл будет увеличиваться. Это упрощает выполнение обратных циклов:

     for a=10, 1, -1 do
       print(a) --> 10, 9, 8, 7, 6, etc.
     end
     

    Если выражение шага не указано, Lua принимает шаг по умолчанию 1.

     for a=1, 10 do
       print(a) --> 1, 2, 3, 4, 5, etc.
     end
     

    Также обратите внимание, что переменная цикла является локальной for цикла for . Он не будет существовать после завершения цикла.

  • Общие for циклов работают через все значения, возвращаемые функцией итератора:

    for key, value in pairs({"some", "table"}) do
      print(key, value)
      --> 1 some
      --> 2 table
    end
     

    Lua предоставляет несколько встроенных итераторов (например, pairs , ipairs ), и пользователи могут определять свои собственные итераторы, а также использовать общие for циклов.

делать блоки

local a = 10
do
    print(a) --> 10
    local a = 20
    print(a) --> 20
end
print(a) --> 10
 

Привет, мир

Это приветственный мировой код:

print("Hello World!")
 

Как это устроено? Это просто! Lua выполняет функцию print() и использует строку "Hello World" качестве аргумента.

Монтаж

Бинарные

Бинарные файлы Lua предоставляются большинством дистрибутивов GNU / Linux в качестве пакета.

Например, на Debian, Ubuntu и их производных можно получить, выполнив следующее:

sudo apt-get install lua50
 
sudo apt-get install lua51
 
sudo apt-get install lua52
 

В SourceForge есть некоторые полуофициальные сборки для Windows, MacOS и некоторых других операционных систем.

Пользователи Apple также могут легко установить Lua с помощью Homebrew :

brew install lua
 

(В настоящее время Homebrew имеет 5.2.4, для 5.3 см. Homebrew / версии .)

Источник

Источник доступен на официальной странице . Приобретение источников и их создание должны быть тривиальными. В системах Linux должно быть достаточно:

$ wget http://lua.org/ftp/lua-5.3.3.tar.gz
$ echo "a0341bc3d1415b814cc738b2ec01ae56045d64ef ./lua-5.3.3.tar.gz" | sha1sum -c -
$ tar -xvf ./lua-5.3.3.tar.gz
$ make -C ./lua-5.3.3/ linux
 

В приведенном выше примере мы в основном загружаем исходный tarball с официального сайта, проверяем его контрольную сумму и извлекаем и выполняем make . (Дважды проверьте контрольную сумму на официальной странице .)

Примечание: вы должны указать, какую цель сборки вы хотите. В этом примере мы указали linux . Другие доступные цели сборки включают solaris , aix , bsd , freebsd , macosx , mingw и т. Д. Для получения более подробной информации macosx doc/readme.html , который включен в источник. (Вы также можете найти последнюю версию README в Интернете .)

Модули

Стандартные библиотеки ограничены примитивами:

  • Функции управления сопрограммой coroutine - coroutine
  • debug - отладочные крючки и инструменты
  • io - основные примитивы ввода-вывода
  • функциональность управления package модулей
  • string - строка и функциональная совместимость с Lua
  • table - примитивы для обработки существенного, но сложного типа Lua - таблицы
  • os - основные операции ОС
  • utf8 - базовые примитивы UTF-8 (начиная с Lua 5.3)

Все эти библиотеки могут быть отключены для конкретной сборки или загружены во время выполнения.

Сторонние библиотеки Lua и инфраструктура для распространения модулей редки, но улучшаются. Такие проекты, как LuaRocks , Lua Toolbox и LuaDist , улучшают ситуацию. Много информации и множество предложений можно найти на старшей Lua Wiki , но имейте в виду, что некоторые из этих данных довольно старые и устаревшие.

Некоторые сложные вещи

Иногда Lua не ведет себя так, как можно было бы подумать после прочтения документации. Некоторые из этих случаев:

Ниль и Ничто не то же самое (ОБЩИЙ ПИТФАЛ!)

Как и ожидалось, table.insert(my_table, 20) добавляет значение 20 в таблицу, а table.insert(my_table, 5, 20) добавляет значение 20 в 5-ю позицию. Что делает table.insert(my_table, 5, nil) ? Можно было бы ожидать, что он будет обрабатывать nil как никакой аргумент вообще и вставить значение 5 в конце таблицы, но фактически добавляет значение nil в пятую позицию таблицы. Когда это проблема?

(function(tab, value, position)
    table.insert(tab, position or value, position and value)
end)({}, 20)
-- This ends up calling table.insert({}, 20, nil)
-- and this doesn't do what it should (insert 20 at the end)
 

Аналогичная ситуация происходит с tostring() :

print (tostring(nil)) -- this prints "nil"
table.insert({}, 20) -- this returns nothing
-- (not nil, but actually nothing (yes, I know, in lua those two SHOULD
-- be the same thing, but they aren't))

-- wrong:
print (tostring( table.insert({}, 20) ))
-- throws error because nothing ~= nil

--right:
local _tmp = table.insert({}, 20) -- after this _tmp contains nil
print(tostring(_tmp)) -- prints "nil" because suddenly nothing == nil
 

Это также может привести к ошибкам при использовании стороннего кода. Если, например, документация некоторых состояний функций «возвращает пончики, если повезет, нуль в противном случае», реализация может выглядеть примерно так:

function func(lucky)
    if lucky then
        return "donuts"
    end
end
 

эта реализация может показаться разумной вначале; он возвращает пончики, когда это необходимо, и когда вы вводите result = func(false) результат будет содержать значение nil .

Тем не менее, если нужно написать print(tostring(func(false))) lua выдаст ошибку, которая выглядит примерно так stdin:1: bad argument #1 to 'tostring' (value expected)

Это почему? tostring явно получает аргумент, хотя его nil . Неправильно. func ничего не возвращает, поэтому tostring(func(false)) является тем же, что и tostring() и NOT то же, что и tostring(nil) .

Ошибки, говорящие о «ожидаемом значении», являются убедительным доказательством того, что это может быть источником проблемы.

Устранение пробелов в массивах

Это огромная ошибка, если вы новичок в lua, и в таблице есть много информации