LuaIniziare con Lua


Osservazioni

Logo Lua

Lua è un linguaggio di scripting minimalista, leggero e integrabile. È stato progettato, implementato e gestito da un team della PUC-Rio , la Pontificia Università Cattolica di Rio de Janeiro in Brasile. La mailing list è aperta per essere coinvolta.

Casi di utilizzo comuni per Lua includono la creazione di script di videogiochi, l'estensione di applicazioni con plug-in e config, l'involuzione di alcune logiche di business di alto livello o semplicemente l'incorporamento in dispositivi come TV, automobili, ecc.

Per attività ad alte prestazioni esiste un'implementazione indipendente che utilizza il compilatore just-in-time disponibile chiamato LuaJIT .

Versioni

Versione Gli appunti Data di rilascio
1.0 Versione iniziale, non pubblica. 1993/07/28
1.1 Prima versione pubblica. Documento della Conferenza che lo descrive. 1994/07/08
2.1 A partire da Lua 2.1, Lua è diventata disponibile gratuitamente per tutti gli scopi, compresi gli usi commerciali. Documento ufficiale che lo descrive. 1995/02/07
2.2 Stringhe lunghe, l'interfaccia di debug, migliori stackback di stack 1995/11/28
2.4 Compilatore luac esterno 1996/05/14
2.5 Funzioni di corrispondenza del modello e vararg. 1996/11/19
3.0 Introdotto auxlib, una libreria per aiutare a scrivere le librerie Lua 1997/07/01
3.1 Funzioni anonime e chiusure di funzioni tramite "upvalues". 1998/07/11
3.2 Libreria di debug e nuove funzioni di tabella 1999/07/08
3.2.2 2000/02/22
4.0 Stati multipli, istruzioni "for", aggiornamento API. 2000/11/06
4.0.1 2002-07-04
5.0 Coroutine, metatables, scoping lessicale completo, chiamate di coda, booleans passano alla licenza MIT. 2003/04/11
5.0.3 2006-06-26
5.1 Revamp del sistema di moduli, garbage collector incrementale, metatables per tutti i tipi, luaconf.h revamp, parser completamente rientranti, argomenti variadici. 2006-02-21
5.1.5 2012-02-17
5.2 Garbage collector di emergenza, goto, finalizzatori per tavoli. 2011-12-16
5.2.4 2015/03/07
5.3 Supporto UTF-8 di base, operazioni bit a bit, interi 32/64 bit. 2015/01/12
5.3.4 Ultima versione. 2017/01/12

Commenti

Commenti a riga singola in Lua iniziano con -- e continuano fino alla fine della riga:

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

Blocca i commenti che iniziano con --[[ e termina con ]] :

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

I commenti di blocco utilizzano lo stesso stile di delimitatore di stringhe lunghe; qualsiasi numero di segni di uguale può essere aggiunto tra parentesi per delimitare un commento:

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

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

Un trucco per commentare blocchi di codice è circondarlo con --[[ e --]] :

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

Per riattivare il blocco, aggiungi semplicemente una - alla sequenza di apertura del commento:

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

In questo modo, la sequenza -- nella prima riga inizia un commento a riga singola, proprio come l'ultima riga, e l'istruzione di print non è commentata.

Facendo un ulteriore passo avanti, due blocchi di codice possono essere impostati in modo tale che se il primo blocco viene commentato, il secondo non lo sarà, e viceversa:

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

Per attivare il secondo blocco mentre disabiliti il ​​primo blocco, elimina l'iniziale - nella prima riga:

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

Esecuzione di programmi Lua

Di solito, Lua viene spedito con due file binari:

  • lua - interprete indipendente e shell interattiva
  • compilatore luac -bytecode

Diciamo che abbiamo un programma di esempio ( bottles_of_mate.lua ) come questo:

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
 

Il programma stesso può essere eseguito eseguendo in seguito sulla tua shell:

$ lua bottles_of_mate.lua
 

L'output dovrebbe assomigliare a questo, correndo nel ciclo infinito:

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.
...
 

Puoi compilare il programma nel bytecode di Lua eseguendo il seguente comando sulla tua shell:

$ luac bottles_of_mate.lua -o bottles_of_mate.luac
 

Anche l'elenco bytecode è disponibile eseguendo quanto segue:

$ 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
 

Iniziare

variabili

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.
 

tipi

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!"
 

Il tipo speciale nil

Un altro tipo in Lua è nil . L'unico valore nel nil tipo è nil . nil esiste per essere diverso da tutti gli altri valori in Lua. È un tipo di valore non valore.

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!
 

espressioni

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
 

Definizione di funzioni

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
 

booleani

Solo false e nil valutano come false, tutto il resto, incluso 0 e la stringa vuota vengono valutate come vere.

raccolta dei rifiuti

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

tavoli

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.
 

Queste sono le basi, ma c'è una sezione sulle tabelle con maggiori informazioni.

condizioni

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

per loops

Ci sono due tipi di loop for in Lua: un ciclo numerico for loop e un ciclo for generico.

  • Un ciclo numerico for ha la seguente forma:

    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
     

    La terza espressione in un ciclo numerico for è il passo in base al quale il ciclo aumenterà. Ciò facilita i cicli di inversione:

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

    Se l'espressione del passo viene omessa, Lua assume un passo predefinito di 1.

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

    Si noti inoltre che la variabile loop è locale al ciclo for . Non esisterà dopo che il ciclo è finito.

  • Generico for cicli lavoro attraverso tutti i valori che una funzione iteratore restituisce:

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

    Lua fornisce diverse costruita nel iteratori (ad esempio, pairs , ipairs ), e gli utenti possono definire i propri iteratori ordinazione pure da utilizzare con generico for cicli.

fare blocchi

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

Ciao mondo

Questo è ciao codice mondiale:

print("Hello World!")
 

Come funziona? È semplice! Lua esegue la funzione print() e usa la stringa "Hello World" come argomento.

Installazione

Binari

I binari Lua sono forniti dalla maggior parte delle distribuzioni GNU / Linux come un pacchetto.

Ad esempio, su Debian, Ubuntu e le loro derivate può essere acquisito eseguendo questo:

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

Ci sono alcune build semi-ufficiali fornite per Windows, MacOS e alcuni altri sistemi operativi ospitati su SourceForge .

Gli utenti Apple possono anche installare facilmente Lua usando Homebrew :

brew install lua
 

(Attualmente Homebrew ha 5.2.4, per 5.3 vedere Homebrew / versioni .)

fonte

La fonte è disponibile nella pagina ufficiale . L'acquisizione di fonti e la costruzione di se stessa dovrebbero essere banali. Sui sistemi Linux dovrebbe essere sufficiente quanto segue:

$ 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
 

Nell'esempio sopra stiamo fondamentalmente scaricando un tarball sorgente dal sito ufficiale, verificandone il checksum ed estraendo ed eseguendo make . (Controlla il checksum nella pagina ufficiale ).

Nota: è necessario specificare quale target di build si desidera. Nell'esempio, abbiamo specificato linux . Altri obiettivi di costruzione disponibili includono solaris , aix , bsd , freebsd , macosx , mingw , ecc. Per ulteriori dettagli, mingw doc/readme.html , che è incluso nella fonte. (Puoi anche trovare l'ultima versione del README online .)

moduli

Le librerie standard sono limitate alle primitive:

  • coroutine - funzionalità di gestione di coroutine
  • debug - ganci e strumenti di debug
  • io - I / O primitivi di base
  • package - funzionalità di gestione dei moduli
  • string e funzionalità di corrispondenza specifica del modello Lua
  • table - primitive per trattare un tipo di Lua essenziale ma complesso - tabelle
  • os - operazioni di base del sistema operativo
  • utf8 - primitive UTF-8 di base (dal Lua 5.3)

Tutte queste librerie possono essere disabilitate per una build specifica o caricate in fase di esecuzione.

Librerie e infrastrutture Lua di terze parti per la distribuzione di moduli sono scarse, ma migliorano. Progetti come LuaRocks , Lua Toolbox e LuaDist stanno migliorando la situazione. Molte informazioni e molti suggerimenti possono essere trovati sul vecchio Lua Wiki , ma sappiate che alcune di queste informazioni sono piuttosto vecchie e obsolete.

Alcune cose complicate

A volte Lua non si comporta come si potrebbe pensare dopo aver letto la documentazione. Alcuni di questi casi sono:

Nil e Nothing non sono gli stessi (COMUNE PITFALL!)

Come previsto, table.insert(my_table, 20) aggiunge il valore 20 alla tabella e table.insert(my_table, 5, 20) aggiunge il valore 20 alla 5a posizione. Cosa fanno invece table.insert(my_table, 5, nil) ? Ci si potrebbe aspettare che trattino nil come nessun argomento, e inserisca il valore 5 alla fine della tabella, ma in realtà aggiunge il valore nil alla 5a posizione della tabella. Quando è un problema?

(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)
 

Una cosa simile accade con il 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
 

Ciò potrebbe anche causare errori durante l'utilizzo di codice di terze parti. Se, ad esempio, la documentazione di alcuni stati di funzione "restituisce ciambelle se fortunati, altrimenti nulla", l'implementazione potrebbe sembrare un po 'come questa

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

questa implementazione potrebbe sembrare ragionevole all'inizio; restituisce le ciambelle quando deve, e quando si digita result = func(false) result conterrà il valore nil .

Tuttavia, se si scrivesse la print(tostring(func(false))) lua genererebbe un errore simile a questo stdin:1: bad argument #1 to 'tostring' (value expected)

Perché? tostring ottiene chiaramente una discussione, anche se è nil . Sbagliato. func non restituisce nulla, quindi tostring(func(false)) è lo stesso di tostring() e NOT lo stesso di tostring(nil) .

Errori che dicono "valore atteso" sono una forte indicazione che questa potrebbe essere la fonte del problema.

Lasciare spazi vuoti negli array

Questa è una trappola enorme se sei nuovo a lua e ci sono molte informazioni nella categoria delle tabelle