Lua

programovací jazyk From Wikipedia, the free encyclopedia

Lua
Remove ads

Lua je odlehčený, vysokoúrovňový, reflexivní, multiparadigmatický, imperativní a procedurální programovací jazyk navržený jako skriptovací jazyk s rozšiřitelnou sémantikou. Název je odvozen z portugalského slova pro měsíc.

Stručná fakta Paradigma, Vznik ...
Remove ads

Historie

Lua vytvořili v roce 1993 Roberto Ierusalimschy, Luiz Henrique de Figueiredo a Waldemar Celes, členové Computer Graphics Technology Group (Skupina technologie počítačové grafiky) na Papežské univerzitě v Rio de Janeiro v Brazílii. Verze Lua předcházející verzi 5.0 byly uveřejněny pod licencí podobnou BSD licenci, od verze 5.0 je Lua distribuován pod licencí MIT.

Lua byl použit v mnoha komerčních aplikacích (např. v adventuře firmy LucasArts Escape from Monkey Island a software ovládajícím roboty) stejně jako těch nekomerčních (Angband a jeho varianty). Mezi jeho nejbližší příbuzné lze řadit Icon pro jeho design a Python pro snadnost použití i pro neprogramátory.

V roce 2008 bylo vytvořeno jedno z nejznámějších vývojových prostředí pro jazyk Lua (Corona SDK). V roce 2009 byl vytvořen engine pro 2D hry Love2D.

Remove ads

Vlastnosti

Jazyk Lua je určen jako rozšiřující nebo skriptovací jazyk a je dostatečně malý, aby se vešel na nejrůznější hostitelské platformy. Podporuje jen malé množství atomárních datových struktur jako jsou boolovské hodnoty, čísla (implicitně s dvojitou přesností plovoucí čárky) a řetězce. Běžné datové struktury jako jsou pole, množiny, hashovací tabulky, seznamy a záznamy mohou být reprezentovány použitím jediné nativní datové struktury – tabulky, která je v podstatě heterogenním asociativním polem. Jmenné prostory a objekty mohou být vytvořeny taktéž za použití tabulek. Zahrnutím minimálního počtu datových typů se Lua pokouší dosáhnout rovnováhy mezi silou a velikostí.

Sémantika Lua může být rozšiřována a měněna předefinováním některých zabudovaných funkcí v metatabulkách. Navíc podporuje Lua pokročilé vlastnosti, jako jsou funkce vyššího řádu a garbage collector. Kombinací mnoha těchto vlastností je možné v Lua psát i objektově orientované programy.

Lexikální konvence

V Lua může být jméno (také nazývané identifikátor) jakýkoli řetězec písmen, čísel a podtržítek, který nezačíná číslicí. Tato definice je v souladu s definicí jmen ve většině jazyků. Definice písmene závisí na jazyce (místním): současný jazyk považuje jakýkoli znak písmene za použitý jako identifikátor. Identifikátory se používají k pojmenování proměnných a polí tabulky.[1]

Následující klíčová slova jsou vyhrazena a nelze je použít jako identifikátory:

and break do else elseif end false for function if in local nil not or repeat return then true until while

Lua rozlišuje velká písmena od malých; takže and je vyhrazené slovo, ale And a AND dvě různá platná jména. Názvy, které začínají podtržítkem a velkými písmeny (jako např _VERSION), jsou podle konvence vyhrazeny pro vnitřní globální proměnné používané jazykem Lua.

Následující řetězce označují další lexikální symboly: + - * / % ^ # - == ~= <= >= < > = - ( ) { } [ ] ; : , . .. ...

Remove ads

Ukázky kódu

Deklarace a inicializace proměnných:

local a, b, c = true, "string", 1

Klasický program Hello world lze napsat následovně:

print('Hello, world!')

Cyklus for (For loop), který vypíše čísla 1 až 10, lze napsat následovně:

for i = 1, 10 do
    print(i)
end

Jiný krok než 1 je třeba uvést jako třetí hodnotu před do; pro vypsání čísel od 100 do nuly klesajících po 5 lze použít

for i = 100, 0, -5 do
    print(i)
end

Algoritmus TBK

Podrobnější informace naleznete v článku Algoritmus TBK.
local function f(t)
  return math.sqrt(math.abs(t)) + 5 * t ^ 3
end

local a = {}
for i = 1, 11 do
  a[i] = io.read("*number")
end

for i = #a, 1, -1 do
  local y = f(a[i])
  print(i - 1, y > 400 and "TOO LARGE" or y)
end

Funkce

Výpočet faktoriálu ukazuje rekurzivní volání funkce:

function factorial(n)
    if n <= 0 then
        return 1
    end

    return n * factorial(n - 1)
end

Výpočet prvních n dokonalých čísel:

function perfeitos(n)
   cont=0
   x=0
   print("Dokonalá čísla jsou:")
   repeat
      x=x+1
      suma=0
      for i=1,(x-1) do
         if math.mod(x,i)==0 then suma=suma+i;
         end
      end
      if suma == x then
         print(x)
         cont = cont+1
      end
   until cont==n
   print("Stiskněte libovolnou klávesu pro ukončení...")
end

Použití funkcí jako objektů první kategorie je ukázáno na následujícím příkladu, kde je modifikováno chování funkce print:

do
   local oldprint = print -- uloží "print" do "oldprint"
   print = function(s)    -- předefinuje funkci "print"
      if s == "foo" then
         oldprint("bar")
      else
         oldprint(s)
      end
   end
end

Jakékoli volání funkce print nyní vyvolá novou funkci a díky lexikálnímu rozsahu jazyka Lua bude stará funkce print přístupná pouze prostřednictvím nové.

Uzávěry a možnost funkce v proměnné („prvotřídní“ funkce):

function make_adder(x)
  return function(a)
    return a+x
  end
end

add7 = make_adder(7)
r = add7(3)     --  =>  r == 10

Při každém vyvolání funkce make_adder se pro proměnnou x vytvoří nový uzávěr, takže anonymní funkce, která se vrátí, bude vždy přistupovat k vlastní hodnotě proměnné x. Uzávěr spravuje sběrač odpadků jazyka (garbage collector), stejně jako jakýkoli jiný objekt.

Funkce v jazyce Lua jsou pouze jednou kategorií proměnných. Lze je definovat také takto:

local foo = function(a,b,c)
    print('variable "foo"')
end

Nebo mohou být v tabulkách:

local myTable = {'item 1', function() print('table item 2') end, 3}

Příkazy cyklu

Jazyk Lua má 4 typy cyklů: while (s testem na začátku), repeat (s testem na konci), for a generickou smyčku. Jejich syntaxe jsou uvedeny níže:

while podmínka do
    -- příkazy
end
repeat
    -- příkazy
until podmínka
for i = začátek, konec, krok do -- krok může být kladný i záporný
    -- příkazy
    -- např.: print(i)
end
for key, value in next, some_table do
    -- příkazy
end

Generická smyčka projde všemi dvojicemi (klíč,hodnota) v tabulce. Podobný typ smyčky je v jazyce Python.

Následuje jednoduchý příklad použití:

Remove ads

Tabulky

Tabulky jsou nejdůležitější datovou strukturou (a jediným složeným datovým typem) v jazyce Lua a jsou základem dalších datových typů. Pomocí tabulek je možné simulovat vektory, matice, struktury, objekty atd.

Tabulka je sada klíčů a datových párů známých také jako hashované heterogenní asociativní pole, kde jsou data odkazována klíčem. Klíč (index) může být jakéhokoli datového typu kromě nil. Klíč tvořený celým číslem s hodnotou 1 není totožný s klíčem tvořeným řetězcem "1".

Tabulky se vytvářejí pomocí následující syntaxe: {}

a_table = {} -- vytvoří novou prázdnou tabulku

Při přiřazení se tabulky předávají referencí:

a_table = {x = 10}  -- vytvoří novou tabulku, která obsahuje jednu dvojici klíč-hodnota, klíči "x" je přiřazena hodnota 10
print(a_table["x"]) -- vypíše hodnotu přiřazenou klíči "x", což je 10
b_table = a_table
a_table["x"] = 20   -- hodnota přiřazená klíči "x" v tabulce a_table se změní na 20
print(a_table["x"]) -- vypíše hodnotu přiřazenou klíči "x" v tabulce a_table, což je 20
print(b_table["x"]) -- vypíše hodnotu přiřazenou klíči "x" v tabulce b_table, což je také 20, protože příkazem b_table = a_table se předal odkaz na tabulku

Tabulky jako vektor

Pokud se při vytváření tabulky zadají pouze hodnoty, budou jim přiřazeny celočíselné klíče, které je identifikují. Na rozdíl od jiných programovacích jazyků má však první index hodnotu 1, nikoli 0.

Následuje příklad, jak můžete simulovat použití vektoru pomocí tabulky v Lua:

array = { "a", "b", "c", "d" } -- hodnotám jsou automaticky přiřazeny klíče 1, 2, 3, 4
print(array[2])                -- vypíše "b"
print(#array)                  -- vypíše 4, operátor # dává poslední index, který je kladné celé číslo
array[0] = "z"                 -- index 0 není součástí seznamu, ale asociativního pole
print(#array)                  -- vypíše 4, poslední index, který je kladné celé číslo

Vymazání prvku, iterátor

Přiřazením hodnoty nil dojde k vymazání prvku. Po vymazání prvků se operátor # může chovat zmatečně. Všechny položky tabulky lze projít iterátorem pairs:

array = { "a", "b", "c", "d" } -- hodnotám jsou automaticky přiřazeny klíče 1, 2, 3, 4
print(array[2])                -- vypíše "b"
array[2] = nil
print(#array)                  -- vypíše 4
array[4] = nil
print(#array)                  -- vypíše 1
for key, value in pairs(array) do
  print(string.format("%s: %s", key, value))
end

Tabulky jako struktura

Tabulky se často používají jako struktury, ve kterých jsou jednotlivé položky rozlišeny pomocí identifikátorů. Lua má speciální syntaxi pro přístup k těmto položkám. Příklad:

point = { x = 10, y = 20 } -- vytvoří novou tabulku
print(point["x"])          -- vypíše hodnotu položky s klíčem "x", to jest 10
print(point.x)             -- jiný způsob přístupu k téže položce

Příklad vektoru struktur:

function Point(x, y)       -- konstruktor objektů "Point"
   return { x = x, y = y } -- vytvoří a vrátí objekt (tabulku)
end
array = { Point(10, 20), Point(30, 40), Point(50, 60) } -- vytvoří pole objektů "Point"
print(array[2].y)                                       -- vypíše 40 (y-ová souřadnice 2. prvku pole array)

Tabulka jako matice

Příklad tabulky simulující jednoduchou matici:

matice =
{
    {1, 2, 3, 4},
    {5, 6, 7, 8}
}
print(matice[1][3]) -- vypíše 3 (3. položka z 1. řádku)
print(matice[2][4]) -- vypíše 8 (4. položka z 2. řádku)

Tabulky jako objekty

Přestože součástí jazyka Lua nejsou objekty, toto paradigma je možné používat díky dvěma rysům jazyka: funkce jsou objektem první kategorie a tabulek. Objekt se vytvoří umístěním funkcí a souvisejících dat do tabulky.

Pomocí metatables lze také implementovat koncept dědičnosti a požádat objekt, aby hledal metody nebo atributy, které v nadřazených objektech neexistují.

Následně bude jako příklad vytvořen vektorový objekt, pomocí zjednodušené syntaxe, kterou jazyk poskytuje pro OOP:

local Vektor = { } -- vytvoří třídu "Vektor"
Vektor.__index = Vektor

function Vektor:new(x, y, z) -- konstruktor
    return setmetatable({x = x, y = y, z = z}, Vektor)
end

function Vektor:magnitude()
    -- na atributy objektu se odkazujeme pomocí "self"
    return math.sqrt(self.x^2 + self.y^2 + self.z^2)
end

local vec = Vektor:new(0, 1, 0) -- vytvoří objekt třídy Vektor
print(vec:magnitude()) -- volání metody (vypíše 1)
print(vec.x) -- přístup k atributu (vypíše 0)

Další příklad konstrukce třídy a objektově orientovaného programování lze vidět níže.

local Vektor = { }

do -- nový blok
    Vektor.init = function(x, y, z) -- konstruktor
        self = setmetatable({ x = x, y = y, z = z }, {__index=Vektor})
        return self
    end

    function Vektor:magnitude() -- metoda objektu
        return math.sqrt(self.x^2 + self.y^2 + self.z^2)
    end
end

local vec = Vektor.init(0, 1, 0) -- vytvoří objekt třídy Vektor
print(vec:magnitude()) -- volání metody (vypíše 1)
print(vec.x) -- přístup k atributu (vypíše 0)

Jazyk Lua je natolik flexibilní, intuitivní a dynamický, že může implementovat téměř jakýkoli koncept z jiných programovacích jazyků, který v jazyce Lua chybí; použijí se metatables.

Metatables

Základním rysem jazyka Lua je rozšiřitelná sémantika a koncept „metatables“, který umožňuje rozsáhlé přizpůsobování tabulek jazyka Lua. Následující příklad ukazuje „nekonečnou“ tabulku. Pro jakoukoli hodnotu „n“ je „fibs[n]“ n-té Fibonacciho číslo získané pomocí dynamického programování.

fibs = { 1, 1 } -- počáteční hodnoty fibs[1] a fibs[2]
meta_table = setmetatable(fibs, {
    __index = function(name, n) -- __index je předdefinovaná funkce, která se vyvolá, pokud klíč "n" neexistuje
    name[n] = name[n - 1] + name[n - 2] -- spočítá a vypíše fibs[n].
    return name[n]
    end
})
print (meta_table[3]) -- vypíše 2
Remove ads

Vnitřní postupy

Programy v Lua nejsou přímo interpretovány, ale jsou kompilovány do bajtkódu, který je následně spuštěn na Lua virtual machine (virtuálním stroji). Proces kompilace je obvykle pro uživatele transparentní a je prováděn za běhu programu. Lze jej však vyvolat offline za účelem zvýšení výkonu nebo omezení velikosti obrazu v paměti hostujícího prostředí vynecháním kompilátoru.

Následující příklad ukazuje výpis bajtkódu výše popsané funkce pro výpočet faktoriálu (v Lua 5.1):

function <factorial.lua:1,7> (10 instructions, 40 bytes at 0x805ee50)
1 param, 3 slots, 0 upvalues, 1 local, 3 constants, 0 functions
    1	[2]	LE       	0 0 -1	; compare value to 0
    2	[2]	JMP      	2	; to line 5
    3	[3]	LOADK    	1 -2	; 1
    4	[3]	RETURN   	1 2
    5	[6]	GETGLOBAL	1 -3	; factorial
    6	[6]	SUB      	2 0 -2	; - 1
    7	[6]	CALL     	1 2 2
    8	[6]	MUL      	1 0 1
    9	[6]	RETURN   	1 2
   10	[7]	RETURN   	0 1
Remove ads

Aplikace

Lua se uplatňuje především v mnoha hrách, jako je World of Warcraft, masivní onlinová multiplayerová hra na hrdiny, ve které si mohou uživatelé přizpůsobit uživatelské rozhraní, animace postav a vzhled světa právě v jazyku Lua, a sérii Baldur's Gate a videohře MDK2, kde je použit jako skriptovací jazyk pro moduly. Také se objevuje v některých open source hrách, jakými jsou Battle for Wesnoth, Daimonin a hry ve stylu Rogue: ToME a H-World. Skripty v jazyce Lua jsou také využity u her Worms 3D, Worms 4: Mayhem, Mafia II, Roblox a v modifikaci pro GTA V, FiveM. Therescript, použitý k řízení vozidel a animací v There, je mírně upravená verze Lua. Správce oken Ion nebo Awesome používají Lua pro své přizpůsobování a rozšiřování. Program Chat Mapper pro zapisování a ukládání rozhovorů (například mezi postavami ve hrách) používá jazyk Lua k řízení rozhovoru. Program LuaTeX rozšiřuje primitivní příkazy TeXu o možnost zadávání kódu v jazyce Lua.

Je udržován seznam projektů, o nichž se ví, že používají Lua.[2]

Remove ads

Knihy

Odkazy

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads