Aiuto:Lua
Questa è un'introduzione per fornire un primo orientamento per chi è nuovo a Lua/Scribunto, il linguaggio utilizzato per creare i moduli. Non vuol essere una guida generale alla programmazione in Lua (ce ne sono già tante sul Web) ma all'uso specifico nel caso dei moduli di Cathopedia.
Se non sei interessato alla programmazione, ma solo all'uso di programmi già fatti, vedi Aiuto:Moduli.
Generalità
Lua è un linguaggio di programmazione implementato in Cathopedia con alcune sostanziali restrizione mediante Scribunto. Il suo scopo è di permettere di processare i dati disponibili sulle pagine di Cathopedia per organizzarne in maniera personalizzata la visualizzazione.
Il reference manual originale del linguaggio è ben scritto, comprensivo e informativo, ma può essere problematico per i principianti perché presenta caratteristiche che non funzionano su Cathopedia a cominciare dalla funzione print()
, che compare nell'esempio standard "Ciao".
Creare un modulo di prova
I moduli vanno creati nell'omonimo namespace, per le prove è possibile utilizzare una sottopagina di Modulo:Sandbox creando una sottopagina con il proprio nome utente, per cui basta creare una pagina del tipo: Modulo:IlTuoNomeUtente/NomeModulo.
Problemi con l'implementazione corrente
A parte print()
, ci sono altre caratteristiche mancanti: vedi Differences from standard Lua per una lista completa.
Al momento per manipolare le stringhe è consigliabile usare le funzioni della libreria mw.ustring
invece della libreria mw.string
, perché quest'ultima non è in grado di gestire caratteri Unicode e può produrre errori casuali o comportamenti inaspettati (per esempio codici come "UNIQ5ae8f2aa414ff233-h-3--QINU" nel testo transcluso).
Input
I programmi vengono eseguiti solo quando la pagina viene "analizzata sintatticamente" (cioè quando essa o una pagina che la incorpora viene cambiata o visualizzata in anteprima), non ogni volta che viene visualizzata. Pertanto non è possibile realizzare un modulo Lua che permetta di inserire la temperatura in Fahrenheit e ottenere il valore in Celsius, o cliccare su un segmento di un insieme di Mandelbrot per espanderlo. Deve esserci una pagina Wiki attuale (o perlomeno una pagina di cui è stata chiesta l'anteprima) che contenga i dati di input.
Comunque, è possibile usare le funzioni di libreria come mw.title.new
per importare contenuto da ogni testo presente su Cathopedia. Non si può comunque importare dati dai file, neanche da quelli in formato .svg che sono un formato XLM testuale.
Richiamare un modulo Lua
La chiamata a un modulo Lua è simile alla chiamata di un template e consiste di un piccolo blocco di testo come
{{#invoke:HelloWorld|Ciao}}
Questo testo chiama lo script Lua "Ciao" ospitato nel namespace Modulo. L'effetto della chiamata è di inviare le informazioni contenute nel blocco #invoke al modulo Lua e di rimpiazzare tutto quello contenuto nelle parentesi graffe con il testo che viene restituito dal modulo.
Notate che il primo "parametro", in questo caso "Ciao", è in realtà la chiamata di una funzione contenuta nel modulo Lua. Questo campo deve sempre essere incluso nell'istruzione #invoke
. Chi è abituato a usare i normali template di Cathopedia si aspetta che tutto quello che compare dopo il primo |
sia un parametro e la presenza di questo campo può confonderlo. Quando si documenta un modulo è pertanto utile includere degli esempi di uso espliciti in istruzioni come {{nowiki|Ciao|Ciao}}
così che ci si ricordi di inserirlo.
Errori
Se si verifica un errore di esecuzione il blocco invoke
sarà sostituito da una scritta rossa "scribunto-parser-error". Se nel proprio browser è abilitato il Javascript è possibile cliccarci sopra per aprire una finestra popup che contiene una descrizione dettagliata dell'errore e di solito un collegamento che permette di andare direttamente alla riga in cui si è verificato l'errore. Ci sono alcune eccezioni, per esempio nel caso di "Errore script: nessun modulo "$2"." o "Errore script: la funzione "$2" se il nome del modulo o della funzione sono sbagliati.
Output
La parte fondamentale di un programma Lua è l'istruzione return
che restituisce il risultato della funzione alla pagina che contiene l'#invoke
. Una funzione Lua può anche non contenere un'istruzione return, ma sarebbe inutile chiamarla.
Il modulo in sé deve ritornare una tabella di valori, che in Lua sono espressi come una lista di oggetti separati da virgole all'interno di parentesi graffe. Quando il modulo viene chiamato dal comando #invoke il primo parametro del comando (il nome della funzione) viene cercato nella tabella esportata. La funzione viene quindi chiamata e deve ritornare qualcosa rappresentabile come una stringa.
Tipicamente un modulo Lua denominato Saluto avrà la forma:
-- Tutti i moduli Lua su Cathopedia devono iniziare definendo una variabile di tipo tabella che contenga
-- le funzioni accessibili dall'esterno. Può avere qualunque nome e contenere anche altri dati
local tab = {};
-- Viene aggiunta una funzione alla variabile. Questa è richiamabile da Cathopedia mediante il
-- comando #invoke.
-- L'argomento "frame" conterrà i dati che Cathopedia invia a questa funzione, come stai? quando viene
-- chiamata.
function tab.Ciao (frame)
-- L'istruzione successiva termina la funzione e ritorna la stringa "Ciao, come stai?" a Cathopedia
-- che verrà visualizzata al posto del richiamo del comando #invoke
return "Ciao, come stai?"
-- termina la funzione
end
-- Il modulo deve terminare restituendo la variabile che contiene le sue funzioni a Cathopedia
return tab
-- Questo modulo può ora essere usato chiamando {{#invoke: Saluto | Ciao }} restituendo:
-- Ciao, come stai?.
-- Il comando #invoke inizia con il nome del modulo, in questo caso "Saluto",
-- quindi il nome di una delle sue funzioni come argomento, in questo caso "Ciao".
Input
Quando la funzione tab.Ciao
viene chiamata, riceve un argomento di tipo tabella che contiene varie informazioni passate dalla pagina di Cathopedia che effettua la chiamata di {{#invoke: Saluto | Ciao }}
, tra cui gli argomenti della chiamata. L'argomento della funzione può avere qualunque nome Lua valido, ma convenzionalmente su Cathopedia si usa il nome frame
.
frame
contiene un'altra tabella, frame["args"]
che a sua volta contiene i parametri passati nella chiamata di #invoke
, ad eccezione del primo parametro che è stato usato per selezionare il nome della funzione da eseguire. Quindi per esempio se la funzione len
del modulo Modulo:String viene chiamata con {{invoke|String|len|pippo}}
allora frame["args"][1]
conterrà la stringa "pippo".
I parametri nominali sono indicizzati mediante il nome del parametro, mentre quelli posizionali dalla loro posizione nella chiamata della funzione del modulo. Quindi, per esempio con l'istruzione {{#invoke: Saluto | Ciao_nome1 | Pippo | Come va ?}}
verrà richiamata la funzione Ciao_nome1
del modulo Modulo:Saluto a cui saranno passati due parametri posizionali, contenenti rispettivamente la stringa "Pippo" e "Come va?", queste sono accessibili all'interno del modulo usando le istruzioni frame.args[1]
e frame.args[2]
Un esempio di chiamata con parametri nominali è {{#invoke: Saluto | Ciao_nome2 | nome=Pippo | saluto=Come va ?}}
in cui verrà chiamata la funzione Ciao_nome2
che riceverà due parametri nominali, nome
e saluto
, anch'essi contenenti le stringhe "Pippo" e "Come va?". In questo caso il loro contenuto è accessibile con le istruzioni frame.args["nome"]
e frame.args["saluto"]
. Se il nome del parametro contiene solo caratteri alfabetici, numeri e il carattere underline (e non inizia con un numero), si può accedere al suo valore anche con l'istruzione frame.args.nome_parametro
, quindi nell'esempio sopra con frame.args.nome
e frame.args.saluto
.
frame
contiene un puntatore al frame "padre", quello della pagina che ha chiamato la funzione e che può essere usato a sua volta per recuperare questi argomenti. Basta usare il comando
parent=frame.getParent(frame)
e parent.args
conterrà questi argomenti.
Un'abbreviazione per il comando sopra è parent=frame:getParent()
, in cui il primo parametro (frame
) viene sottinteso usando i due punti.
Debug
Si può testare il programma fin dall'inizio semplicemente usando la concatenazione di stringhe. Basta usare una variabile con un nome riconoscibile come "debuglog" nella vostra funzione principale con un'istruzione come local debuglog=""
(deve essere inizializzata a una stringa vuota altrimenti avrebbe un valore nil
e concatenargli una stringa genererebbe un errore). Adesso ogni volta che si vuole testare una variabile, diciamo x
basta scrivere un'istruzione come debuglog = debuglog .. "x=" .. tostring(x)
e al termine del programma inserire il codice return output .. debuglog
, dove per output si intende il valore che dovrebbe essere ritornato normalmente, a cui viene concatenato il valore di debuglog. La funzione tostring
serve ad assicurarsi che il valore della variabile x
venga forzato al tipo stringa, così che se un altro tipo di valore verrà mostrata come "table", "nil", etc. piuttosto che generare un errore di script.
Stile
Le regole che seguono sono solo indicative:
- Usare 4 spazi per l'indentazione e non usate tabulazioni, l'editor di codice di Cathopedia usa 4 spazi.
- Cercate di limitare la lunghezza di una singola riga così che persone con monitor più piccoli possano comunque leggere con facilità il codice. Se una riga fosse troppo lunga l'istruzione può essere spezzata su linee multiple con l'indentazione allineata con la parentesi di apertura. Le condizioni di un istruzione
if
dovrebbero essere piazzate sulla linea successiva.
- Evitate spazi inutili nelle chiamate di funzioni o di tabelle. Non usate spazi immediatamente prima o dopo delle parentesi di apertura (
[, (, {
) e di chiusura (], ), }
)
- Non mettete istruzioni multiple sulla stessa riga a meno che l'istruzione non sia molto breve
- I commenti si iniziano con un doppio tratto
--
. Usateli, anche se molti moduli di Cathopedia sono semplici, usare dei commenti chiari vi aiuterà quando vi troverete a modificare del codice scritto da un altro autore o che non modificate da molto tempo.
Errori tipici
Alcuni tipici errori:
- Attempt to call a string value. Significa che avete dimenticato il
..
tra una stringa e una variabile in una sequenza di concatenazione di stringhe.
- Una variabile ignora i vostri tentativi di assegnarli un valore. Ci sono due istruzioni
local
con il primo che setta il valore in una regione limitata del programma, quando uscite da quella regione questa viene scartata e viene nuovamente usata quella più generale (rimasta al vecchio valore)
- Un valore di una tabella numerata ignora i vostri tentativi di assegnarli un valore. Questo avviene perché
a["50"] ~= a[50]
. Tipicamente avete processato un parametro con una funzione stringa in un posto, ma gli avete assegnato un valore numerico in un altro, lasciandovi con due differenti tipi di variabile da usare come indice.
- ... nil ... Ci sono molte cose che non potete fare con una variabile che abbia valore
nil
, per esempio assegnare un valore a a.1
se a
è nil
, concatenare a .. b
se una delle due è nil
. Inizializzate le variabili con valori sensati come local a=""
o local a={}
, etc. Spesso viene menzionato "global" perché non avete neanche inizializzato una variabile con local
.
- string expected, got function. alcune funzioni come
mw.ustring.gmatch
ritornano funzioni non stringhe.
Comprendere le tabelle e i concetti correlati
- Una lista di espressioni è un insieme di valori separato da virgole. I valori possono essere stringhe, numeri, tabelle, funzioni, ecc...
- Una sequenza è un insieme di valori da 1 a N (dove N è un intero positivo). Può essere creata con una lista di espressioni racchiuse in parentesi quadre . Per esempio se
a={1,"quotation",mw.ustring.gmatch("abca","a"),{2,3,4}}
allora a[1]=1
, a[2]="quotation"
, a[3]
è la funzione restituita da gmatch
e a[4]
è la tabella {2,3,4}
. Una lista di espressioni può essere recuperata da una tabella con l'istruzione unpack()
: b,c,d = unpack(a)
assegnerà b=1
, c="quotation"
e d
alla funzione.
- Una tabella è una sequenza supportata opzionalmente da chiavi con nome:
digit["two"]="2"
. Diverse funzioni come table.concat
funzionano solo con gli indici numerici e ignoreranno le chiavi con nome.
- Una metatable offre un vasto insieme opzionale di metodi per alterare il comportamento di una tabella. Per esempio potete definire una tabella in modo che sia richiamabile come una funzione.
Funzione
- Una funzione può ritornare qualunque tipo di variabile, inclusa una funzione. Questa è una caratteristica potente che può facilmente confondere un principiante. Per esempio l'istruzione
a=mw.ustring.gmatch(text,"(.)")
assegnerà ad a
una funzione, o un valore stringa, in questo caso una funzione che ogni volta che viene chiamata ritornerà uno dei caratteri della stringa text
fino ad esaurirli ed a ritornare nil
. Molte funzioni iteratrici funzionano in questa maniera.
- Potete mantenere conteggi separati per funzioni iteratrici usando variabili differenti. Per esempio con l'istruzione
q=mw.ustring.gmatch(text,"(.)")
potete estrarre caratteri dalla stessa stringa dell'esempio precedente valutando d=q()
senza che questo modifichi il comportamento di a()
.
- Le funzioni che devono essere chiamate da un'istruzione
{{#invoke|...}}
devono essere della forma p.myFunctionName
, dove p
è la tabella che viene esportata al termine del modulo", altre funzioni sono locali al modulo e possono avere qualunque nome valido, ma non saranno accessibili dall'esterno del modulo.
Pagine correlate
Collegamenti esterni