Lua (programazio lengoaia)

Lua programazio lengoaia interpretatutako lengoaia inperatibo, egituratua eta arina da. Portugesez Lua-k ilargia esan nahi du. Lua multiplataforma da, ANSI C-n idatzita dagoelako, eta C API erlatiboki sinple bat dauka.

Hasieran Lua software aplikazioetan handitzen zihoan pertsonalizazio eskaerak betetzeko diseinatua izan zen. Programazio lengoaia prozedural gehienen oinarrizko funtzioak bete ahal zituen, baina beste funtzionalitate zailagoak edota domeinu espezifikoko lengoaien ezaugarriak ez zeuden bere barne. Bestalde, lengoaia handitzeko mekanismoak zituen, funtzionalitate hauek gehitzeko ahalbidetzen zutenak. Lua sistema integratuentzat diseinatuta zegoenez, bere garatzaileek abiadura, eramangarritasuna, hedapena eta garapenean erraztasuna hobetzean fokatu ziren.

Historia 
Lua 1993an sortu zuten Roberto Ierusalimschyk, Luis Henrique de Figueiredok eta Waldemar Celesek, Konputagailu Grafikoen Teknologia Taldeko (Tecgraf) kide ziren Rio de Janeiroko Unibertsitate Pontifiko Katolikoan, Brasilen.

1977tik 1992ra, Brasilek merkataritzako hesi gogorrak (merkatu erreserba deituak) aplikatu zituen konputagailu software eta hardwarearentzako. Egoera horretan, Tecgrafen bezeroek ezin zuten software pertsonalizatua erosi kanpotik. Arrazoi honengatik Tecgrafek behar zituen oinarrizko erremintak ezerezetik inplementatu behar izan zituen.

Luaren "ama eta aita" historikoak SOL (Simple Object Language) eta DEL (Data-entry Language) izan ziren. 1992 eta 1993 artean Tecgrafengatik sortuak izan ziren malgutasuna gehitzeko proiektu batzuei (biak ingeniaritzarako programa grafikoak izan ziren Petrobras enpresan). SOL eta DEL-ek ez zuten fluxu kontrolerako egiturarik, eta Petrobras programazio potenteago baten beharrean zegoen.

Lengoaiaren sortzaileek hau idatzi zuten The Evolution of Lua liburuan:

Lua 1.0 SOL-en data deskriptoreen sintaxia zuten objektu eraikitzaileak inkorporatu zituen (horregatik deitzen da Lua - sol Portugesez eguzkia da; lua ilargia). Luaren kontrol egitura sintaxia gehienbat Modulatik hartua izan zen (if, while, repeat/until), baina CLU (hainbat esleipen eta hainbat return funtzio deietatik, erreferentzia parametroen eta puntero esplizituen ordez), C++("ideia ona aldagai lokalak behar den lekuetan bakarrik deklaratzea"), SNOBOL eta AWKtik (bektore asoziatiboak). Dr. Dobb's Journalen argitaratutako artikulu batean, Luaren sortzaileek LISP eta Scheme ere lengoaiaren datu egitura nagusia taulak izatearen erabakian asko eragin zietela diote, haien datu egitura ubikuoarengatik (listak).

Luaren semantika Schemerengatik aldatuak izan dira denbora pasa ahala, gehienbat funtzio anonimo eta esparru lexiko osoen sarrerarekin.

Lua 5.0 bertsioaren aurrekoak BSD lizentziarekin atera ziren. 5.0 bertsiotik aurrera, Luak MIT lizentzia erabiltzen du. Biak dira software libre permisibo lizentziak, eta ia identikoak dira.

Ezaugarriak 
Lua programazio lengoaia trinkoa da, beraz plataforma askotan erabili daiteke. Aldagaiek ez dute motarik, bakarrik datuak izan daitezke logikoak, osoak, koma flotagarria edo kateak. Bektoreak, pilak, hash taulak, listak eta erregistroak taulekin (Luan dagoen datu egitura bakarra) errepresentatu daitezkeen datu egiturak dira.

Lua multiparadigma lengoaia da bere semantika hedatu eta aldatu egin ahal delako, datu egituren funtzioak aldatuz metataulak erabiliz, Perl bezala (honela herentziak sartu daitezke adibidez, nahiz eta lengoaian berezkoak ez izan).

Luak ordena altuko funtzioak erabili ditzake, eta zabor biltzailea ere. Hauek konbinatuz, Lua objektuei bideratutako programazioan erabili daiteke. Beste ezaugarri batzuk mota bihurketa, koerrutinak eta modulu dinamikoen karga dira, besteak beste.

Datu mota kantitate txikia duenez bere barne, Lua ahalmen eta tamainaren arteko oreka bat mantentzen saiatzen da.

Sintaxia 
Kaixo mundua adibidea:
print("Hello, World!")

Honela ere idatzi daiteke:
io.write("Hello, World!\n")

edo Lua orrian emandako adibidea:io.write("Kaixo Mundua, ", _VERSION, "tik!\n")Iruzkinek hurrengo sintaxia erabiltzen dute, Ada, Eiffel, Haskell, SQL eta VHDL antzera:-- Lua iruzkinak bi gidoiekin hasten dira eta lerroaren amaierararte funtzionatzen dute.

--[[ Hainbat lerrotako iruzkinak eta kateak
    kortxeteak erabiltzen dituzte. ]]

--[=[ Mota honetako iruzkinek beste --[[iruzkin batzuk]] izan ahal dituzte bere barnean. ]=]Funtzio faktoriala hurrengo adibidean bezala inplementatzen da:function factorial(n)
  local x = 1
  for i = 2, n do
    x = x * i
  end
  return x
end

Iterazioak 
Luak lau iterazio edo begizta mota ditu: while, repeat (do while-en antzekoa) for begizta numerikoa, eta for begizta generikoa.--baldintza = true

while baldintza do
  --deklarazioak
end

repeat
  --deklarazioak
until baldintza

for i = first,last,delta do --delta negatiboa izan daiteke, i aldagaia aurrera edo atzera kontatzen utziz
  --deklarazioak
  --adibidea: print(i)
endFor begizta generikoa:for key, value in pairs(_G) do
  print(key, value)
end_G taula iteratuko luke, pairs funtzio iteratiboa erabiliz, nulua bueltatzen duen arte.

Habiatutako begiztak (begizta bat beste begizta baten barnean) ere egin daitezke.local objektuak = { "kaixo", "epa" }

for i,v in pairs(_G) do
    for indizea,balioa in pairs(objektuak) do
        print(objektuak[indizea])
        print(balioa)
    end
end

Funtzioak 
Luaren funtzioen tratamendua ordena altuko balio bezala hurrengo adibidean erakusten da, print funtzioaren portaera aldatzen duena:do
  local oldprint = print
  -- Print funtzioa oldprintera aldatu
  function print(s)
    --[[ Print funtzioa berdefinitu, print normala oldprinten bidez deitu daiteke. Berriak argumentu bakarra dauka.]]
    oldprint(s == "foo" and "bar" or s)
  end
endEdozein print dei funtzio berritik pasatuko da orain, eta Luaren esparru lexikoaengatik, print funtzio zaharra funtzio berritik bakarrik erabili ahal izango da.

Luak itxidurentzako euskarria du, behean erakusten den bezala:function gehitu(x)
  -- Funtzio bat bueltatu x gehitzen diona argumentuari
  return function(y)
    --[=[ x aldagaiaz hitz egiten ari garenean, esparru honen kanpoan dagoena
       eta bere bizi-zikloa funtzio anonimo hau baino laburragoa izango dena, 
       Luak itxidura bat sortzen du.]=]
    return x + y
  end
end
gehilau = gehitu(4)
print(gehilau(3)) -- 7 bueltatzen du

--Hau ere funtzioa honako era honetan deituz lortu daiteke:
print(gehitu(4)(3))
--[[ Hau bueltatzen den 'gehitu(4)' funtzioa '3' argumentuarekin zuzen deitzen ari garelako gertatzen da.
     Honek datuen kostua erreduzitzen ditu eta errendimiendua hobetzen du iteratiboki deitzerakoan.
]]Gehitu funtzioa deitzen den bakoitzean itxidura berri bat sortzen da x aldagaiarentzako, beraz funtzio bakoitzak bere x parametroa erabiliko du, erroreak saihestuz. Itxidura Luaren zabor biltzaileak kudetuko du, edozein objektu bezala.

Taulak 
Taulak Luan dauden datu egitura garrantzitsuenak (diseinuz, dauden datu mota konposatu bakarrak) dira, eta erabiltzaileak sortutako datu mota guztien oinarria. PHPko bektore asoziatiboen, Pythonen hiztegien eta Perl edo Rubyren hashen kontzeptu antzerakoak dituzte.

Taulak datu eta gakoez osatutako pare bilduma da, non datua gakoarengatik erreferentziatuta dagoen. Gako bat (indizea) edozein balio (nulua eta NaN izan ezik) izan daiteke. 1 balioa duen gako numerikoa "1" kate gakoaren desberdina dela kontuan hartuko da.

Taulak {} sintaxia duen eraikitzailea erabiltzen sorten dira:

taula_bat = {} -- Taula berri eta hutsa sortzen duTaulak beti erreferentzialki erabiltzen dira (ikus. Objektu deia)taula_bat = {x = 10} -- Taula berri bat sortzen du, "x" gakoa 10 baliora apuntatzen
print(taula_bat["x"]) --[[ Kate gakoarekin asoziatuta dagoen balioa bueltatzen du,
                        kasu honetan 10.]]
taula_bi = taula_bat
taula_bi["x"] = 20 -- Taularen balioa "x" gakoan 20 balioa da orain
print(taula_bi["x"]) -- 20 bueltatzen du.
print(taula_bat["x"]) --[[ 20 ere bueltatzen du, taula_bat eta taula_bi taula
                        berdinera apuntatzen dutelako.]]

Erregistro bezala 
Taulak askotan egitura (edo erregistro) bezala erabiltzen dira kateak erabiliz gako bezala. Erabilera hori hain komuna denez, Luak sintaxi berezia dauka eremu horietan sartzeko. Adibidez:puntua = { x = 10, y = 20 } -- Taula berria sortu
print(puntua["x"]) -- 10 bueltatzen du
print(puntua.x) --[[ Goiko lerroaren berdina egiten du, irakurterraza
                                den puntu notazioa azukre sintaktikoa bakarrik da.]]Lua 5.3 Erreferentzia Manualean agertzen den bezala:

Izen tarte bezala 
Taula batean bere funtzio erlazionatuak gordetzean, izen tarte bezala funtzionatu dezake.Puntua = {}

Puntua.new = function(x, y)
  return {x = x, y = y}  --  return {["x"] = x, ["y"] = y}
end

Puntua.set_x = function(puntua, x)
  puntua.x = x  --  point["x"] = x;
end

Bektore bat bezala 
Gako numeriko bat erabiliz, taulak bektore datu motak izan daitezke. Lua bektoreak 1-oinarrikoak dira: lehenengo indizea 1 da eta ez 0 beste programazio lengoaia asko bezala (baina 0 indizea esplizituki gehitu daiteke)

Kate bektore sinple bat:bekt = { "a", "b", "c", "d" } -- Indizeak automatikoki ezartzen dira.
print(bekt[2]) -- "b" bueltatzen du, Luaren indizea 1etik hasten delako.
print(#bekt) -- 4 bueltatzen du. # taulen eta kateen luzera jakiteko operandoa da.
bekt[0] = "z" -- Zero indize legala da.
print(#bekt) -- 4 bueltatzen du oraindik, Lua bektoreak 1-oinarrikoak direlako.T taularen luzera edozein integer n izan daiteke, beraz t[n] ez da nulua eta t[n+1] nulua da; t[1] nulua bada, n zero izan daiteke. Bektore erregulark batentzat, balio ez nuluekin 1etik n-ra, bere luzera n hori da, azken balioaren indizea. Bektoreak "zuloak" baditu (hau da, balio nuluak nuluak ez diren balioen artean), orduan #t balio nulu bat baino lehenago dagoen edozein indize izan daiteke. Beraz, edozein balio nulu hartu dezake bektorearen amaiera bezala.

Bi dimentsioko taula:NireTaula =
{
     {1,2,3,4},
     {5,6,7,8}
}
print(NireTaula[1][3]) -- "3" bueltatzen du
print(NireTaula[2][4]) -- "8" bueltatzen duObjektu bektore bat:function Puntu(x, y) -- "Puntu" objektu eraikitzailea
  return { x = x, y = y }   -- Objektu berria sortu eta bueltatzen du (taula)
end
bekt = { Puntu(10, 20), Puntu(30, 40), Puntu(50, 60) } -- Puntu bektore bat sortzen du
                        -- bekt = { { x = 10, y = 20 }, { x = 30, y = 40 }, { x = 50, y = 60 } };
print(bekt[2].y)Hash taulak erabiltzea bektore bat emulatzeko normalean bektorea bera erabiltzea baino geldoagoa da. Lua taulak bektore bezala erabiltzeko optimizatuta daude arazo hau saihesteko.

Metataulak 
Semantika hedagarria Luaren zati garrantzitsu bat da, eta metataula kontzeptuak Lua taulak era potentean pertsonalizatzea ahalbidetzen du. Hurrengo adibideak taula "infinitua" adierazten du. Edozein -rako, fibs[n] . Fibonacciren zenbakia bueltatuko du programazio dinamikoa eta memoizazioa erabiliz.fibs = { 1, 1 } -- Hasierako balioak fibs[1] eta fibs[2]rentzako.
setmetatable(fibs, {
  __index = function(balioak, n)                --[[ __index Luak duen berezko funtzio bat da,
                                                    "n" gakoa existitzen ez bada deitzen zaio. ]]
    balioak[n] = balioak[n - 1] + balioak[n - 2]  -- fibs[n] kalkulatu eta memoizatu.
    return balioak[n]
  end
})

Objektuetara bideratutako programazioa 
Nahiz eta Luak klaseen kontzeptua berez inplementatuta ez eduki, lengoaiak dituen bi ezaugarrirekin gehitu daitezke: ordena altuko funtzioak eta taulak. Funtzioak eta haiekin erlazionatuta dauden datuak taula batean sartuz, objektu bat sortzen da. Herentzia (singularra eta plurala) metataula mekanismoarekin inplementatu daitezke, objektuari metodo ezezagunak eta eremuak bere aita objektuan/etan esanez.

Ez dago "klase" kontzeptu bat teknika hauekin, termino zehatzagoa prototipoa izango litzateke, Self eta JavaScript moduko lengoaietan bezala. Objektu berriak factory method (objektu berriak zerotik sortzen dituena) edo existitzen den proiektu bat klonatzen sortzen dira.

Luak azukre sintaktikoa dauka bere barnean objektuetata bideratutako programazioa errazagoa egiteko. Objektu baten metodoak prototipo taula batean adierazteko, taula:func(args) funtzioa erabili daiteke, taula.func(self, args)-en berdina dena. Klase metodoak deitzerakoan bi puntu erabili daitezkeBar object:funrgs), object.func(object, args)-en berdina dena.

Oinarrizko bektore objektu baten adibidea:local Bektore = {}
Bektore.__index = Bektore

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

function Bektore:magnitude() -- Beste metodo bat
  -- 'self' erabiliz gure objektua erreferentziatu dezakegu
  return math.sqrt(self.x^2 + self.y^2 + self.z^2)
end

local bek = Bektore:new(0, 1, 0) -- Bektore objektu bat sortu
print(bek:magnitude()) -- Metodo bat deitu (irteera: 1)
print(bek.x) -- Objektuaren aldagai bati dei egin (irteera: 0)

Barnekoak 
Lua programak ez dira zuzenean testu fitxategitik interpretatzen; bytecodean konpilatzen dira eta makina birtual batean exekutatzen dira. Konpilazio prozesua ikustezina izaten da erabiltzailearentzat eta exekuzio denboran egiten da. Jada konpilatuta dauden fitxategiak erabili daitezke errendimiendua igotzeko eta memoria erabilera gutxitzeko. Lua bytecodea lengoaian produzituta eta exekutatuta izan daiteke ere, string liburutegiko dump funtzioa eta load/loadstring/loadfile funtzioak erabiliz. Lua 5.3.3 bertsioak 24000 C lengoaieko lerro ditu bere barnean.

PUZ gehienek bezala, eta makina birtual gehienek ez bezala (piletan oinarrituta daudenak), Lua VM erregistroak erabiltzen ditu, eta beraz egungo hardware diseinutik hurbil dabil. Erregistro arkitekturak beharrezkoak ez diren balioen kopiak sahiesten ditu eta funtzio bakoitzeko instrukzio gutxiago erabiltzen dira. Lua 5en makina birtuala erabilera asko duen erregistroetan oinarritutako VM puruetako bat da. Perlen Parrot eta Androiden Dalvik dira beste bi erregistroetan oinarritutako VM ezagunak.

Hemen ikusi dezakegu goiko funtzio faktorialaren bytecode zerrenda (luac 5.1 konpilatzaileak erakusten duen bezala):

 function <factorial.lua:1,7> (9 instructions, 36 bytes at 0x8063c60)
 1 param, 6 slots, 0 upvalues, 6 locals, 2 constants, 0 functions
 	1	[2]	LOADK    	1 -1	; 1
 	2	[3]	LOADK    	2 -2	; 2
 	3	[3]	MOVE     	3 0
 	4	[3]	LOADK    	4 -1	; 1
 	5	[3]	FORPREP  	2 1	; to 7
 	6	[4]	MUL      	1 1 5
 	7	[3]	FORLOOP  	2 -2	; to 6
 	8	[6]	RETURN   	1 2
 	9	[7]	RETURN   	0 1

C API 
Lua beste aplikazio batzuen barnean egoteko diseinatuta dago, eta C API bat eskaintzen du honetarako. APIa bi zatitan dago: Lua nukleoa eta Lua liburutegi osagarria.

Luaren API diseinuak C lengoaieko erreferentzia kudeaketa manuala saihesten du, Pythonen APIa ez bezala. API hau, lengoaiaren bezala, minimalista da. Funtzio konplexuagoak liburutegi osagarriak ahalbidetzen ditu, gehienbat aurreprozesatzaile makroez osatuta dagoena eta taula operazio konplexuetan laguntzen duena.

Pilak 
Lua C APIa piletan oinarrituta dago. Luak C datu mota sinpleenekin (integerrak, floatak, etab.) push eta pop egiteko eta pilan taulak manipulatzeko funtzioak dauzka. Luaren pila pila tradizional baten ezberdina da nolabait; pila hauei zuzenean indize bat esleitu dakieke, adibidez. Indize negatiboak pilaren goikaldetik zenbatera dauden adierazten dute, beraz, -1 pilaren goikaldea adierazten du (hau da, sartu den balio berriena) eta balio positiboek azpitik zenbatera dauden adierazten dute (balio zaharrena).

C eta Luaren arteko datuen marshallinga pila erabiltzen egiten da. Lua funtzio bat deitzeko, argumentuak sartzen dira pilan. Orduan, lua_call erabltzen da funtzioa deitzeko. C funtzio bat Luatik zuzenean deitzeko idazterakoan, argumentuak pilatik irakurtzen dira.

Adibidea 
Honako funtzio honetan Lua funtzio bat deitzen da Ctik:#include <stdio.h>
#include <lua.h> //Lua oinarrizko liburutegia (lua_*)
#include <lauxlib.h> //Lua liburutegi osagarria (luaL_*)

int main(void)
{
    //Lua deklarazio bat sortu
    lua_State *L = luaL_newstate();

    //string (kate) bat kargatu eta exekutatu
    if (luaL_dostring(L, "function foo (x,y) return x+y end")) {
        lua_close(L);
        return -1;
    }

    //"foo" globalaren (goian dagoen funtzioaren) balioa 
    //stackean sartu, 5 eta 3 integerrez jarraitua
    lua_getglobal(L, "foo");
    lua_pushinteger(L, 5);
    lua_pushinteger(L, 3);
    lua_call(L, 2, 1); //bi argumentu eta bueltzatze balio bakarra duen funtzio bat deitu
    printf("Result: %d\n", lua_tointeger(L, -1)); //pilaren goikaldean dagoen integer balioa idatzi
    lua_close(L); //Lua deklarazioa itxi
    return 0;
}
Adibide hau exekutatzeak hau bueltatzen du:

 $ cc -o example example.c -llua 
 $ ./example 
 Result: 8

Taula bereziak 
C APIak taula bereziak eskaintzen ditu, Lua pilaren "pseudo-indize" batzuetan kokatuak. Lua 5.2 baino lehen LUA_GLOBALSINDEX da globalen taula, _G Luaren barnean, eta oinarrizko izen tartea da. LUA_REGISTRYINDEX erregistro bat ere dago non C programak Lua balioak gorde dezaketen, gero erabiltzeko.

Hedapena eta atzipena 
Posiblea da hedapen moduluak idaztea Lua APIa erabiliz. Hedapen moduluak interpretatzailearen funtzionalitatea hedatzeko balio duten liburutegi dinamikoak dira. Lua aldetik, modulua izen tarte taula bat bezala agertuko da bere funtzio eta aldagaiekin. Lua programak hedapen moduluak kargatu ditzakete require erabiliz, Luan idatzitako moduluek bezala.

LuaRocks pakete kudeaketa sistemak Lua modulu asko dauzka aukeran, CPAN, RubyGems eta Python Eggsen antzera. Moduluei rock deitzen zaie, eta handik datorkio izena. Beste modulu batzuk http://lua-users.org/ daukan wikian aurkitu daitezke.

Aurreidatzitako Lua atzipenak jada existitzen dira programazio lengoaia erabilienetan. C++en txantiloi batzuk daude eta atzipen sortzaile automatikoak ere.

Aplikazioak

Bideo-jokoak 
Bideo-jokoen garapenean, Lua scripting lengoaia oso erabilia da, beharbada bere lizentzia zabaldua, exekuzio arina, integrazio maila eta ikasketa kurba laburrarengatik. Crytek eta CryEngine motore grafikoak Lua eta C++ean diseinatuta daude.

2012. urtean, TigForums webguneko erabiltzaile batek jokoentzarako scripting lengoaia erabiliena zein zen galdetu zuen inkesta batean, eta Lua atera zen irabazle diferentzia handi batekin. 2012ko Urtarrilaren 12an Game Developer aldizkariaren Front Line Award 2011 irabazle agertu zen Lua Programazio Erreminten kategorian.

Erreferentziak

Kanpo estekak 
  Webgune ofiziala

Programazio lengoaiak
Plataforma anitzeko softwarea
Sistema txertatuak