Obsah
1. Knihovny a frameworky pro programovací jazyk Lua
2. Standardní knihovny dodávané s interpretrem jazyka Lua
3. Vstupně-výstupní operace
4. Matematické funkce, práce s řetězci a s tabulkami
5. Externí knihovny
6. Webové servery a frameworky
7. Alternativní implementace překladače a interpretru Lua
8. Rozšíření sémantiky jazyka – metalua
9. Odkazy na Internetu
1. Knihovny a frameworky pro programovací jazyk Lua
V předchozích částech tohoto seriálu jsme v demonstračních příkladech již mnohokrát použili některé funkce ze standardních knihoven jazyka Lua, které jsou dodávány již v základní instalaci spolu s překladačem a interpretrem. Funkce nabízené těmito knihovnami budou popsány ve druhé, třetí i čtvrté kapitole. V navazujících kapitolách si stručně popíšeme některé zajímavé externí knihovny, zejména ty, které jsou dodávané s licencemi umožňujícími použití těchto knihoven ve vlastních projektech bez zásadních licenčních omezení (LGPL apod.). Použitelných externích knihoven v současnosti existuje již značné množství, od jednoduchých knihoven určených například pro numerické výpočty, přes různé grafické a multimediální knihovny a knihovny umožňující snadnou tvorbu grafického uživatelského rozhraní (s využitím GTK+ apod.) až po poměrně rozsáhlé webové frameworky, které obsahují jak podporu pro příjem a následné zpracování HTTP požadavků (tj. vlastní jednovláknový či vícevláknový webový server), tak i funkce pro přístup k relačním databázím, zpracování XML i JSON formátu, snadnou tvorbu dynamických HTML stránek s využitím šablon atd.
2. Standardní knihovny dodávané s interpretrem jazyka Lua
V základní instalaci jazyka Lua je, prakticky bez ohledu na použitou platformu, přítomno i několik standardních knihoven, jejichž funkce je možné volat z Lua skriptů a nepřímo též z céčkového programu v případě, že je interpretr jazyka Lua zabudován do větší aplikace. Standardní knihovny pokrývají základní potřeby tvůrců skriptů – usnadňují zpracování řetězců i asociativních polí, nabízí matematické funkce, funkce pro práci se soubory a pro styk s operačním systémem (vytvoření nového procesu apod.) a v neposlední řadě nabízí i rozhraní pro externí debuggery a profilery kódu (toto rozhraní je v případě potřeby možné použít i pro jiné účely, ovšem z několika důvodů to není tvůrci jazyka doporučováno). Většina funkcí ze základních knihoven je umístěna ve vlastním jmenném prostoru (namespace), tj. jedná se o funkce uložené do vhodně pojmenovaného asociativního pole, ovšem nejčastěji používané funkce a proměnné nemají vlastní jmenný prostor a jsou tak přístupné přímo pod svým jménem (před kterým se neuvádí jmenný prostor oddělený od jména tečkou). Jedná se o následující funkce a proměnné (podrobnějším popisem některých dále vypsaných funkcí se budeme zabývat v navazujících částech tohoto seriálu):
Název funkce/proměnné | Popis |
---|---|
_G | proměnná obsahující globální prostředí, do nějž jsou ukládány všechny funkce i proměnné |
_VERSION | proměnná obsahující jméno a verzi interpretru jazyka Lua v řetězcové podobě |
assert | kontrola, zda je zadaná podmínka splněna; v případě jejího nesplnění je vypsáno chybové hlášení (lze použít i pro typovou kontrolu) |
collectgarbage | funkce, pomocí níž je možné spustit, zastavit či nakonfigurovat garbage collector, jenž se stará o uvolňování paměti po již neaktivních objektech |
dofile | soubor, který je této funkci předán jako parametr, je spuštěn jako Lua skript |
error | výpis chybového hlášení a ukončení právě probíhající chráněné funkce (viz další část tohoto seriálu) |
getfenv | vrací prostředí, ve kterém je spuštěna právě aktivní funkce |
getmetatable | tuto funkci jsme již použili v předchozích částech seriálu – slouží pro získání metatabulky nějakého objektu |
ipairs | i tuto funkci již známe – lze ji využít pro získání iterátoru, pomocí nějž lze iterovat přes všechny prvky pole |
load | načtení (nebo zkonstruování) bloku příkazů zadanou callback funkcí |
loadfile | načtení bloku příkazů ze souboru zadaného svým jménem |
loadstring | načtení bloků příkazů z řetězce (ten může být například získán deserializací skriptu z archivu nebo zkonstruován na základě uživatelského vstupu) |
next | lze použít pro procházení tabulkou – pro zadanou tabulku a index prvku vrátí index dalšího prvku v tabulce i hodnotu tohoto prvku |
pairs | tato funkce vrací pro zadanou tabulku trojici hodnot: funkci next, vlastní tabulku a hodnotu nil, takže ji lze využít pro konstrukci smyčky za účelem procházení tabulky |
pcall | spuštění funkce v chráněném režimu |
základní funkce pro výpis hodnot na standardní výstup, která akceptuje libovolný počet a typ parametrů | |
rawequal | zjištění, zda jsou dva objekty shodné bez volání metametody __eq z metatabulky, lze tak obejít přetížení tohoto operátoru |
rawget | získání hodnoty uložené na zadaném indexu v tabulce (asociativním poli) bez volání metametody __index z metatabulky – i tato funkce tedy obchází uživatelsky přetížené operátory |
rawset | uložení hodnoty do tabulky (asociativního pole), opět bez volání přetíženého operátoru představovaného metametodou __newindex |
module | vytvoření modulu se zadaným jménem. Podrobnosti o modulech si řekneme v navazujících částech tohoto seriálu. |
require | načtení modulu se zadaným jménem, ovšem jen tehdy, pokud již daný modul není načtený |
select | získání hodnot všech parametrů uložených za parametrem se zadaným indexem, popř. získání počtu těchto parametrů |
setfenv | nastavení prostředí pro zvolenou funkci |
setmetatable | nastavení metatabulky pro zadaný objekt |
tonumber | převod řetězcové hodnoty na číslo, lze specifikovat i základ pro převod (dvojková, osmičková, desítková, šestnáctková atd. soustava) |
tostring | převod libovolné hodnoty na řetězec; funkci pro převod na řetězec lze „přetížit“ zápisem události __tostring do metatabulky |
type | pro libovolný objekt vrátí jeho typ v řetězcové podobě (tuto funkci jsme již použili v předchozích částech seriálu) |
unpack | získání několika po sobě uložených položek z tabulky |
xpcall | spuštění funkce v chráněném režimu se specifikací další funkce (předané jako druhý parametr), která je použita pro zpracování chyby (error handler) |
3. Vstupně-výstupní operace
Funkce pro vstupně/výstupní operace jsou rozděleny do dvou standardních knihoven. V knihovně io můžeme najít funkce pracující s implicitním objektem představujícím otevřený soubor (deskriptorem). Tento soubor je nejprve otevřen a jeho deskriptor je uschován přímo v asociativním poli io). Naproti tomu knihovna file obsahuje funkce použitelné jako metody – jejich prvním parametrem je vždy deskriptor otevřeného souboru, proto lze místo volání typu file.názevFunkce(deskriptor) použít syntaktický cukr a volání provést „objektově“: deskriptor:názevFunkce(), což je nejen kratší, ale i přehlednější (podrobnější informace o této vlastnosti jazyka Lua byla uvedena v části věnované objektově orientovanému programování).
Název funkce | Význam |
---|---|
io.close | uzavření souboru |
io.flush | uložení všech dat z vyrovnávacích pamětí |
io.input | otevření souboru v textovém režimu pro čtení |
io.lines | otevření souboru a vrácení iterátoru, který lze použít při čtení dat po celých řádcích |
io.open | otevření souboru v zadaném režimu (čtení, zápis, připojení na konec souboru, binární čtení/zápis/připojení) |
io.output | otevření souboru v textovém režimu pro zápis |
io.popen | spuštění programu v samostatném procesu a získání standardního vstupu či výstupu tohoto programu (lze použít pro posílání či naopak příjem dat) |
io.read | čtení dat ze souboru v uživatelsky nastaveném formátu |
io.stderr | deskriptor souboru představující standardní chybový výstup |
io.stdin | deskriptor souboru představující standardní vstup |
io.stdout | deskriptor souboru představující standardní výstup |
io.tmpfile | vytvoření dočasného souboru, který je smazán po ukončení skriptu |
io.type | zjištění, zda daná hodnota představuje otevřený či uzavřený soubor (vrací se řetězec „file“ popř. „closed file“). Pokud je hodnota jiného typu, vrátí se nil. |
io.write | zápis dat do souboru v uživatelsky nastaveném formátu |
Funkce dostupné z knihovny file:
Název funkce | Význam |
---|---|
file:close | uzavření souboru |
file:flush | vyprázdnění vyrovnávacích pamětí a zápis jejich obsahu do souboru |
file:lines | vrací iterátor, pomocí něhož lze ve smyčce načítat data ze souboru po jednotlivých řádcích |
file:read | načtení dat ze souboru ve specifikovaném formátu |
file:seek | nastavení aktivního místa v souboru, od kterého se bude provádět čtení či zápis |
file:setvbuf | nastavení vyrovnávací paměti pro soubor – vyrovnávací paměť může být zakázána, povolena globálně či povolena jen pro jeden řádek |
file:write | zápis dat – numerických hodnot či řetězců – do souboru |
4. Matematické funkce, práce s řetězci a s tabulkami
Ve standardních knihovnách jazyka Lua jsou dostupné i základní matematické (logaritmické, goniometrické atd.) funkce, funkce zjednodušující práci s řetězci a taktéž funkce pro práci s tabulkami (poli), pomocí nichž lze do tabulek vkládat nové položky, mazat položky či celou tabulku setřídit. Nejprve bude uveden výpis všech dostupných matematických funkcí:
Název funkce | Význam |
---|---|
math.abs | výpočet absolutní hodnoty |
math.acos | arkus kosinus |
math.asin | arkus sinus |
math.atan | arkus tangens |
math.atan2 | arkus tangens volaný se dvěma parametry představujícími dvě přepony pravoúhlého trojúhelníka |
math.ceil | zaokrouhlení směrem ke kladnému nekonečnu |
math.cos | kosinus |
math.cosh | hyperbolický kosinus |
math.deg | převod z radiánů na úhel zadaný ve stupních |
math.exp | ex |
math.floor | zaokrouhlení směrem k zápornému nekonečnu |
math.fmod | výpočet zbytku po dělení |
math.frexp | výpočet hodnot m a e z výrazu x=m2e |
math.huge | vrací nejvyšší reprezentovatelné číslo |
math.ldexp | výpočet m2e |
math.log | přirozený logaritmus |
math.log10 | desítkový logaritmus |
math.max | maximální hodnota z předané sekvence (její délka není omezena) |
math.min | minimální hodnota z předané sekvence (její délka není omezena) |
math.modf | výpočet celé a desetinné části předané hodnoty |
math.pi | konstanta Π |
math.pow | výpočet xy |
math.rad | převod úhlu zadaného ve stupních na radiány |
math.random | vrací náhodné číslo (založeno na céčkové funkci rand()) |
math.randomseed | nastavení „semínka“ pro generátor náhodných čísel |
math.sin | sinus |
math.sinh | hyperbolický sinus |
math.sqrt | druhá odmocnina |
math.tan | tangens |
math.tanh | hyperbolický tangens |
Mezi funkce pro práci s řetězci patří:
Název funkce | Význam |
---|---|
string.byte | vrátí sekvenci numerických hodnot představujících kódy znaků v řetězci |
string.char | opak předchozí funkce – převod sekvence numerických hodnot na řetězec |
string.dump | tato funkce dokáže vrátit řetězcovou reprezentaci funkce předané jako parametr, vhodné pro serializaci (opakem je výše uvedená funkce loadstring) |
string.find | vyhledávání podřetězce v řetězci, lze použít i regulární výraz |
string.format | zadané parametry jsou zformátovány a převedeny na řetězec, odpovídá céčkovské sprintf() |
string.gmatch | vrací iterátor na základě zadaného regulárního výrazu |
string.gsub | globální nahrazení části řetězce na základě regulárního výrazu (velmi užitečná funkce, kterou si ještě popíšeme) |
string.len | vrací délku řetězce |
string.lower | převod znaků na malá písmena |
string.match | zjištění, zda řetězec obsahuje text specifikovaný regulárním výrazem |
string.rep | řetězec předaný jako parametr se n-krát zopakuje ve výsledném řetězci |
string.reverse | vrátí řetězec s opačným pořadím znaků |
string.sub | nahrazení části řetězce na základě regulárního výrazu (velmi užitečná funkce, kterou si ještě popíšeme) |
string.upper | převod řetězce na velká písmena |
Poslední sada funkcí zjednodušuje práci s tabulkami (implementovanými většinou jako asociativní pole):
Název funkce | Význam |
---|---|
table.concat | pomocí této funkce lze hodnoty z tabulky převést na řetězec, v němž jsou jednotlivé položky odděleny zadaným separátorem (například čárkou či středníkem) |
table.insert | vložení nové hodnoty na zadaný index (zbylé položky v poli se posunou) |
table.maxn | vrátí maximální index použitý v tabulce (asociativním poli) |
table.remove | vymazání hodnoty uložené na zadaném indexu (zbylé položky v poli se posunou) |
table.sort | setřídění tabulky, lze zadat i vlastní funkci volanou při porovnávání dvou položek tabulky |
5. Externí knihovny
V úvodních odstavcích této části seriálu o programovacím jazyku Lua jsme si řekli, že v současnosti již existuje velké množství externích knihoven, s jejichž pomocí lze tento jazyk využít v mnoha odvětvích. Pro práci s 2D a 3D grafikou slouží především knihovny luacairo (http://luaforge.net/projects/luacairo/) a LuaGL (http://luagl.wikidot.com/) podporující kromě vlastního OpenGL i GLUT (OpenGL Utility Toolkit); pamětníci multiplatformní herní knihovny Allegro (která původně vznikla na Atari ST a dnes je podporována na DOSu, MS Windows a samozřejmě i Linuxu) jistě ocení existenci LuAllegro (http://luaforge.net/projects/luallegro/) či rozhraní pro knihovnu SDL s podobnou funkcionalitou – LuaSDL. Pro vytváření dynamických souborů PDF lze použít lpdf (http://www.tecgraf.puc-rio.br/~lhf/ftp/lua/#lpdf) a s relačními databázemi postavenými na standardu SQL lze pracovat pomocí LuaSQL. Seznam většiny volně dostupných knihoven lze získat na adrese http://lua-users.org/wiki/LibrariesAndBindings, popřípadě přímo na LuaForge. Některými dalšími knihovnami, určenými například pro tvorbu či skriptování her, se budeme podrobněji zabývat v navazující části tohoto seriálu.
6. Webové servery a frameworky
Programovací jazyk Lua je možné, ostatně jako téměř každý dnes používaný jazyk, použít pro zpracování dotazů posílaných na HTTP server, jejichž výsledkem má být dynamicky generovaná HTML stránka, rastrový obrázek či vektorová kresba, soubor ve formátu PDF či další dynamický obsah vytvářený na základě uživatelova dotazu. Pro úlohy, které se nespouští s příliš velkou frekvencí, nebo v případě, že nemáme jinou možnost (omezení daná provozovatelem serveru) je možné využít rozhraní CGI nabízené prakticky všemi v současnosti používanými webovými servery (práce přes CGI se v podstatě omezuje na zpracování proměnných prostředí, standardního vstupu a tisku na standardní výstup). Toto řešení ovšem není optimální pro často volané dynamické stránky, protože je nutné pro každý dotaz zavolat nový interpretr Lua jako novou úlohu operačního systému, což je – i přes velmi malé systémové nároky interpretru – relativně pomalé. Navíc tvoří samotné zpracování HTTP požadavku mnohdy jen velmi malou část webových aplikací – většinou je zapotřebí komunikovat s databází, zpracovávat XML, číst a zapisovat cookies, uchovávat stav session mezi jednotlivými požadavky, jednoduše generovat výsledné HTTP stránky s využitím šablon atd.
Pro tyto účely lze použít webový framework nazvaný Kepler, který je z větší části představován přímo Lua knihovnami. Tento framework se skládá z více částí, zejména HTTP serveru Xavante (Xavante je mj. i označení jazyka Brazilských domorodců), podporou pro práci s SQL (LuaSQL), podporou rozhraní CGI (CGILua), XML (užitečné například při použití AJAXu na webových stránkách či komunikaci s webovými službami) atd. Nad tímto frameworkem je (můžeme říci, že i jako technologické demo) postavena Wiki nazvaná Sputnik. Ve skutečnosti je většina stránek věnovaných jazyku Lua provozována právě na Sputniku – viz odkazy uvedené v deváté kapitole. Součástí frameworku Kepler je i podpora pro snazší vytváření dynamických stránek. Nejpřímější cestu pro tvorbu dynamických HTML stránek představuje použití knihovny CGILua a takzvaných here řetězců (here string), tj. řetězcových literálů, při jejichž interpretaci jsou zachovány i formátovací znaky, včetně konců řádků – jedná se o řetězce s prakticky libovolnou délkou, které jsou ukončeny dohodnutou sekvencí znaků (většinou se nejedná o uvozovky, protože ty tvoří běžnou součást řetězců). Jednoduchou dynamickou webovou stránku lze vytvořit následujícím způsobem:
cgilua.htmlheader()
cgilua.put([[
<html>
<head>
<title>Hello World</title>
</head>
<body>
<strong>Hello World!</strong>
</body>
</html>]])
Práce s here řetězci však není v případě rozsáhlejší stránky příliš snadná a mnohdy vede k nežádoucímu míchání statického HTML kódu s částmi Lua skriptu. Jednodušší je použít technologii, která je inspirována PHP a JSP (Java Server Pages), při níž je zvolen ve své podstatě opačný postup – namísto Lua skriptu, který se sám stará o postupnou tvorbu HTML stránky, jsou zde do kostry HTML stránky vloženy speciální značky sloužící k zápisu Lua skriptů či vkládání hodnot vypočtených výrazů do vytvářené stránky (náhrada za explicitní volání funkce print). Při pohledu na následující kód bude podobnost s PHP či JSP zřejmá. Tento kód je před svým dalším zpracováním nejprve transformován do podoby validního Lua skriptu a posléze přeložen a interpretován, přičemž výsledkem je HTML stránka zaslaná serverem do uživatelova webového prohlížeče:
<html>
<?lua
if cgilua.QUERY.language == 'english' then
greeting = 'Hello World!'
elseif cgilua.QUERY.language == 'portuguese' then
greeting = 'Olá Mundo!'
else
greeting = '[unknown language]'
end
?>
<head>
<title><%= greeting %></title>
</head>
<body>
<strong><%= greeting %></strong>
</body>
</html>
7. Alternativní implementace překladače a interpretru Lua
Původní překladač a interpretr jazyka Lua je naprogramován v čistém céčku (ANSI/ISO C), ovšem kromě tohoto „etalonu“ (oficiální standard prozatím neexistuje) existují i další implementace jazyka, jejichž výhodou je například to, že je lze snadno zabudovat do aplikací určených pro běhové prostředí .NET či JRE (Java Runtime Environment), aniž by bylo nutné vkládat mezi Lua skripty a tato prostředí mezistupeň v podobě céčkových funkcí. Velmi zdařilou implementací je LuaJ, jež je, jak ostatně už její název napovídá, vytvořena v Javě a lze ji tak použít prakticky na jakémkoli počítači s dostupným JRE (viz ukázkový příklad uvedený níže, ve kterém je v Lua naskriptována jednoduchá aplikace používající pro tvorbu grafického uživatelského rozhraní knihovnu Swing). Samozřejmě existují i poměrně kvalitní implementace Luy pro prostředí .NET s názvy Lua.NET (akademický projekt), LuaCLR (s MIT licencí) a Lua2IL – vid odkazy uvedené v deváté kapitole.
frame = luajava.newInstance( "javax.swing.JFrame", "Texts" );
pane = luajava.newInstance( "javax.swing.JPanel" );
borderFactory = luajava.bindClass( "javax.swing.BorderFactory" )
border = borderFactory:createEmptyBorder( 30, 30, 10, 30 )
pane:setBorder( border )
label = luajava.newInstance( "javax.swing.JLabel", "This is a Label" );
layout = luajava.newInstance( "java.awt.GridLayout", 2, 2 );
pane:setLayout( layout )
pane:add( label )
pane:setBounds( 20, 30, 10, 30 )
borderLayout = luajava.bindClass( "java.awt.BorderLayout" )
frame:getContentPane():add(pane, borderLayout.CENTER )
jframe = luajava.bindClass( "javax.swing.JFrame" )
frame:setDefaultCloseOperation(jframe.EXIT_ON_CLOSE)
frame:pack()
frame:setVisible(true)
local listener = luajava.createProxy("java.awt.event.MouseListener",
{
mouseClicked = function(me)
print("clicked!", me)
end
})
frame:addMouseListener(listener)
Kromě těchto dvou hlavních „alternativních“ překladačů a interpretrů je možné získat překladač a/nebo interpretr jazyka Lua napsaný v Lispu či JavaScriptu (teoreticky je tak možné Luu použít na webových stránkách, i když dvojí interpretace se negativně projeví nižší rychlostí běhu takové aplikace) či překladač do bajtkódu zpracovávaného virtuálním strojem Parrot (tento překladač je kupodivu vytvořen v Perlu a ne v samotné Lua či céčku – samotné virtuální stroje Lua a Parrotu jsou si v mnohém podobné). Zajímavý je taktéž překladač z Lua do céčka, což je vlastně transformátor bajtkódu tohoto jazyka na volání céčkových funkcí – kromě zvýšení rychlosti běhu skriptu je taktéž umožněno šíření přeloženého programu, ve kterém není obsažen ani původní skript ani jeho bajtkód, čímž je umožněno, aby na cílové platformě nemusel být přítomen ani překladač ani interpretr jazyka Lua (důležité například u jednočipových mikropočítačů s omezenou kapacitou operační paměti).
8. Rozšíření sémantiky jazyka – metalua
Velmi zajímavé a současně i užitečné rozšíření původního (ve své podstatě minimalistického) programovacího jazyka Lua představuje projekt metalua. Jedná se o změnu vlastního překladače, který je rozšířen o některé vlastnosti, které můžeme najít například v Lispovských jazycích – podporu maker, metaprogramování a možnosti rozšíření syntaxe jazyka o další jazykové konstrukce (nové operátory, další typy smyček, řídicí struktury atd.). Tyto vlastnosti jsou do překladače přidány takovým způsobem, že je možné vlastní překládaný kód modifikovat na základě speciálních konstrukcí zapisovaných přímo do zdrojového kódu programu (kód, přesněji jemu odpovídající AST – abstract syntax tree, je tedy modifikován v době překladu, nikoli běhu). V Lispovských jazycích je manipulace s překládaným či interpretovaným kódem velmi jednoduchá, protože zde existuje ekvivalence mezi kódem a daty (vše je chápáno jako seznam, přesněji sekvence provázaných tečka-dvojic tvořících binární strom, odpovídající výše zmíněnému AST), tudíž lze s kódem manipulovat stejně jako s jinými daty. Tuto velmi mocnou techniku se tvůrci systému metalua snažili použít i pro jazyk Lua, což se jim v rámci daných možností podařilo. Možnostmi systému metalua se ještě budeme zabývat v následujících částech tohoto seriálu, dnes si pro ilustraci pouze ukážeme některé možnosti, které toto rozšíření může programátorům přinést:
-- rozšíření syntaxe počítané smyčky for při konstrukci pole
x = { i for i = 2, 50, 2 }
-- filtrace hodnot (sudá čísla) na základě zapsané podmínky
y = { i for i = 1, 50 if i%2==0 }
-- přidání ternárního operátoru do sémantiky jazyka
-- (tento operátor je použitý v jazycích odvozených od céčka:
-- C++, Java, JavaScript atd.)
-- Povšimněte si nové konstrukce +{ a }, která v původní Lua neexistuje
local function b(x, suffix)
local v, ontrue, onfalse = mlp.gensym "test", unpack (suffix)
return `Stat{
+{ block:
local -{v}
if -{x} then (-{v}) = -{ontrue} else (-{v}) = -{onfalse or `Nil} end },
v }
end
mlp.expr.suffix:add{ "?", mlp.expr, gg.onkeyword{ ",", mlp.expr }, prec=5, builder=b }
9. Odkazy na Internetu
- LuaForge
http://luaforge.net/ - LuaForge: Project Tree
http://luaforge.net/softwaremap/trove_list.php - lua-users.org
http://lua-users.org/ - Lua Faq
http://lua-users.org/wiki/LuaFaq - Lua Addons
http://lua-users.org/wiki/LuaAddons - Libraries And Bindings
http://lua-users.org/wiki/LibrariesAndBindings - Lua Power Patches
http://lua-users.org/wiki/LuaPowerPatches - Lua Implementations
http://lua-users.org/wiki/LuaImplementations - Metalua
http://metalua.luaforge.net/ - Metalua manual
http://metalua.luaforge.net/manual000.html - luacairo
http://luaforge.net/projects/luacairo/ - LuAllegro
http://luaforge.net/projects/luallegro/ - Kepler Project
http://www.keplerproject.org/ - LuaRocks
http://www.luarocks.org/ - An Extensible Wiki Engine in Lua
http://spu.tnik.org/ - Ukázka customizaci Sputniku
http://spu.tnik.org/en/Sightings - Interactive Lua
http://lua-users.org/wiki/InteractiveLua - LuaGL
http://luagl.wikidot.com/ - lpdf
http://www.tecgraf.puc-rio.br/~lhf/ftp/lua/#lpdf