Aiuto:Lua

Da Wikipedia, l'enciclopedia libera.
(Reindirizzamento da Wikipedia:Lua)
Jump to navigation Jump to search

Questa è un'introduzione per fornire un primo orientamento per chi è nuovo a Lua (il linguaggio utilizzato nei moduli), una funzionalità del software MediaWiki fornita dall'estensione Scribunto. 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 Wikipedia.

Se non sei interessato alla programmazione, ma solo all'uso di moduli già scritti, consulta le pagine correlate.

Generalità[modifica | modifica wikitesto]

Lua è un linguaggio di programmazione implementato su Wikipedia con alcune sostanziali restrizioni mediante Scribunto. Il suo scopo è permettere di processare i dati disponibili sulle pagine di Wikipedia per organizzarne in maniera personalizzata la visualizzazione.

La documentazione principale di Wikipedia in italiano è il manuale di riferimento al Lua, che fornisce un sommario conciso del linguaggio e delle librerie standard. I reference manuals originali del linguaggio sono ben scritti e comprensibili, ma potrebbero risultare problematici per i principianti, in quanto presentano alcune caratteristiche non compatibili con Wikipedia.

Creare un modulo di prova[modifica | modifica wikitesto]

Dato che i moduli funzionano solo nell'omonimo namespace, esiste la pagina Modulo:Sandbox per le prove (analogamente a Wikipedia:Pagina delle prove per gli ordinari esperimenti di modifica). Se si desidera creare un modulo di prova è possibile farlo in una sottopagina di Modulo:Sandbox creandone una con il proprio nome utente, in questo modo: Modulo:Sandbox/IlTuoNomeUtente/NomeModulo.

Implementazione corrente[modifica | modifica wikitesto]

Al momento per manipolare le stringhe è consigliabile utilizzare le funzioni della libreria mw.ustring invece che della mw.string, poiché quest'ultima non è in grado di gestire i caratteri Unicode e può produrre errori casuali o comportamenti inaspettati (per esempio codici come "UNIQ5ae8f2aa414ff233-h-3--QINU" nel testo transcluso).

Richiamare un modulo Lua[modifica | modifica wikitesto]

Esempio di chiamata di un modulo Lua

La chiamata di un modulo Lua è simile a quella di un template e consiste in un piccolo blocco di testo come {{#invoke:HelloWorld|hello}}.

Questo testo invoca lo script Lua "HelloWord" ospitato nel namespace Modulo. L'effetto della chiamata è quello di inviare le informazioni incluse nel blocco invoke al modulo Lua e rimpiazzare quanto contenuto nelle parentesi graffe con il testo che viene restituito dal modulo.

Infatti il primo "parametro", in questo caso "hello", è in realtà la chiamata di una funzione contenuta nel modulo Lua. Questo campo deve sempre essere incluso nell'istruzione #invoke. Chi è abituato all'utilizzo dei normali template di Wikipedia si aspetterebbe che tutto quello che compare dopo il primo | fosse un parametro e la presenza di questo campo potrebbe confonderlo. Quando si documenta un modulo è pertanto utile includere degli esempi d'uso espliciti come {{#invoke:HelloWorld|hello}}, così che ci si ricordi di compilarlo.

Se si verifica un errore di esecuzione, il blocco invoke sarà sostituito dalla scritta rossa "⧼scribunto-parser-error⧽". Se nel proprio browser è abilitato il JavaScript, è possibile cliccare sulla scritta per aprire una finestra pop-up contenente una descrizione dettagliata dell'errore e di solito un collegamento diretto alla riga da correggere. Ci sono alcune eccezioni, per esempio nel caso di "Errore script: nessun modulo "$2"." o "Errore script: la funzione "$2" non esiste." se i nomi del modulo o della funzione sono sbagliati.

Output[modifica | modifica wikitesto]

La parte fondamentale di un modulo 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 allora sarebbe inutile chiamarla.

Il modulo 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 ricercato nella tabella esportata. La funzione viene quindi invocata e deve ritornare qualcosa di rappresentabile come una stringa.

Tipicamente un modulo Lua avrà questa forma:

-- Tutti i moduli Lua su Wikipedia 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 p = {}

-- Viene aggiunta una funzione alla variabile. Questa è richiamabile da Wikipedia mediante il
-- comando #invoke.
-- L'argomento "frame" conterrà i dati che Wikipedia invia a questa funzione quando viene
-- chiamata.
function p.hello( frame )
    -- L'istruzione successiva termina la funzione e ritorna la stringa "HelloWorld" a Wikipedia.
    -- La funzione verrà visualizzata al posto del richiamo del comando #invoke.
    return "Hello, world!"
-- Termina la funzione.
end

-- Il modulo deve terminare restituendo la variabile che contiene le sue funzioni a Wikipedia.
return p

-- Questo modulo può ora essere utilizzato chiamando {{#invoke:HelloWorld|hello}}.
-- Il comando #invoke inizia con il nome del modulo, in questo caso "HelloWorld",
-- quindi il nome di una delle sue funzioni come argomento, in questo caso "hello".

Input[modifica | modifica wikitesto]

I programmi vengono eseguiti solo quando la pagina viene analizzata "sintatticamente" (cioè quando essa o una pagina che la incorpora vengono modificate o mostrate in anteprima), non ogni volta che viene visualizzata. Pertanto non è possibile realizzare un modulo Lua che permetta di inserire una temperatura in Fahrenheit e ottenerne il valore in Celsius o cliccare su un segmento di un insieme di Mandelbrot per espanderlo. Deve esserci una pagina Wiki (o perlomeno una pagina di cui sia stata richiesta l'anteprima) che contenga i dati di input. È comunque possibile utilizzare le funzioni di libreria come mw.title.new per importare contenuto da ogni testo presente su Wiki. Non si possono però importare dati dai file, nemmeno da quelli in formato .svg (nonostante sia un formato XML testuale).

Quando la funzione p.hello viene chiamata, riceve un argomento di tipo tabella che contiene varie informazioni passate dalla pagina di Wikipedia che effettua la chiamata di {{#invoke:HelloWorld|hello}}, tra cui gli argomenti della chiamata stessa. L'argomento della funzione può avere qualunque nome Lua valido, ma convenzionalmente su Wikipedia è utilizzato il nome frame.

frame contiene un'altra tabella, frame.args, che a sua volta contiene i parametri passati nella chiamata di #invoke (fatta eccezione per il primo parametro, usato soltanto per selezionare il nome della funzione da eseguire).

Parametri posizionali[modifica | modifica wikitesto]

  • Se la funzione len del modulo:String viene chiamata con {{#invoke:String|len|Pippo}}, allora frame.args[1] conterrà la stringa "Pippo".
  • Con l'istruzione {{#invoke:HelloWorld|hello_nome1|Pippo|come va}} verrà richiamata la funzione hello_nome1 del modulo:HelloWorld, a cui saranno passati due parametri contenenti rispettivamente le stringhe "Pippo" e "come va". Queste saranno accessibili all'interno del modulo attraverso le istruzioni frame.args[1] e frame.args[2].

Parametri nominali[modifica | modifica wikitesto]

I parametri nominali vengono indicizzati con un nome per il parametro. Un esempio di chiamata con parametri nominali è {{#invoke:HelloWorld|hello_nome2|nome=Pippo|saluto=come va}}, in cui verrà chiamata la funzione hello_nome2 che riceverà i due parametri nome e saluto, contenenti le stringhe "Pippo" e "come va". In questo caso il loro contenuto sarà accessibile con le istruzioni frame.args["nome"] e frame.args["saluto"].

Quando i nomi dei parametri contengono solo caratteri alfabetici, numeri e il carattere underscore (e non iniziano con un numero), è possibile accedere al loro valore anche con l'istruzione frame.args.nome_parametro, quindi nell'esempio sopra con frame.args.nome e frame.args.saluto.

frame:getParent[modifica | modifica wikitesto]

frame contiene un puntatore all'argomento "padre", quello del modulo invocato, utile per recuperare gli argomenti in caso di funzione richiamata da un template, nel momento in cui questo viene incluso all'interno di un'altra pagina. È sufficiente il comando

local args = frame.getParent( frame ).args

e la tabella args conterrà quegli argomenti.

Un'abbreviazione per il comando sopra è frame:getParent().args, in cui il parametro (frame) viene sottinteso dai due punti.

Debuglog[modifica | modifica wikitesto]

Il modulo può essere testato fin dall'inizio, semplicemente usando la concatenazione di stringhe. È sufficiente aggiungere una variabile con un nome riconoscibile come "debuglog" nella funzione da analizzare, con un'istruzione come local debuglog = "" (dev'essere inizializzata con una stringa vuota, altrimenti avrebbe un valore nil e concatenare una stringa genererebbe un errore). La sintassi per testare una variabile x è la seguente:

debuglog = " x = " .. tostring(x)

La funzione tostring impedisce di commettere degli errori: forzerà sempre il valore della variabile x anche in presenza di tabelle Lua o valori nulli.

Al termine del modulo è indispensabile inserire il comando return output .. debuglog, dove "output" indica il valore da ritornare (se stabilito in precedenza) a cui viene concatenato il valore di debuglog.

Se il valore da testare è una tabella o un'altra variabile complessa si può usare invece il seguente codice:

debuglog = " x = " .. mw.text.jsonEncode(x , mw.text.JSON_PRETTY)

Suggerimenti di stile[modifica | modifica wikitesto]

  • Usare il tabulatore per l'indentazione.
  • Limitare la lunghezza di una singola riga così che persone con monitor più piccoli possano comunque leggere con facilità il codice. Una riga troppo lunga può essere spezzata su linee multiple con l'indentazione allineata alla parentesi di apertura. Le condizioni di un'istruzione if dovrebbero essere piazzate su una linea successiva.
  • Evitare spazi inutili nelle chiamate di funzioni e tabelle o prima o dopo le parentesi di apertura ([, (, {) e di chiusura (], ), }).
  • Dividere istruzioni multiple su righe diverse, a meno che non siano molto brevi.
  • Lasciare dei commenti con un doppio -. Usarli è davvero utile: anche nei moduli più semplici, dei commenti chiari aiutano a modificare del codice scritto da altri autori o non modificato da tempo.

Errori[modifica | modifica wikitesto]

Alcuni tipici errori:

  • Una variabile ignora qualunque tentativo di assegnarle un valore. Sono presenti due istruzioni local e la prima setta il valore in una regione limitata del modulo: uscendo da quella regione, questa viene scartata in favore dell'istruzione generale (rimasta al vecchio valore).
  • Un valore di una tabella numerata ignora i tentativi di assegnargliene un altro. Questo avviene perché a["50"] ≠ a[50]. Processare un parametro rimandante alla funzione di una riga, con un secondo valore numerico collocato su una riga differente, lascia al modulo due diversi tipi di variabile da usare come indice.
  • Attempt to call a string value. L'identificatore .. è stato dimenticato tra una stringa e una variabile in una sequenza di concatenzione.
  • ... nil ... Un valore nullo impedisce diverse azioni, per esempio assegnare un valore ad a.1 se a è nil o la concatenazione a .. b se una delle due è nil. È indispensabile inizializzare le variabili con dei valori come local a = "" o local a = {}. In assenza di una variabile inizializzata con local, viene spesso utilizzato anche global.
  • string expected, got function. Alcune funzioni come mw.ustring.gmatch ritornano funzioni e non stringhe.

Concetti base[modifica | modifica wikitesto]

  • Una lista di espressioni è un insieme di valori (stringhe, numeri, tabelle, funzioni, etc.) separati da virgole.
  • Una sequenza è un insieme di valori che vanno da 1 a N (dove N è un intero positivo). Può essere creata racchiudendo tra parentesi graffe una lista di espressioni. Per esempio se a = {1, "quotation", mw.ustring.gmatch( "abca", "a" ), {2, 3, 4}} allora a[1] = 1, a[2] = "quotation", a[3] equivale al valore restituito dalla funzione 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) restituirà b = 1, c = "quotation" e d alla funzione.
  • Una tabella è una sequenza supportata opzionalmente da chiavi con nome, per esempio digit["two"] = "2". Va però ricordato che diverse funzioni come table.concat richiedono necessariamente gli indici numerici e ignorano questo tipo di chiavi.
  • Una metatable offre svariati metodi per alterare il comportamento di una tabella. Permette anche di definirne una in modo che sia richiamabile come una funzione.

Funzioni[modifica | modifica wikitesto]

  • Una funzione può ritornare qualunque tipo di variabile, inclusa una funzione. Questa è una caratteristica potente che potrebbe confondere un principiante. Un esempio è l'istruzione a = mw.ustring.gmatch( text, "(.)" ) che assegnerà ad a una funzione e non il valore di una stringa. In questo caso la funzione ritornerà ad ogni chiamata uno dei caratteri della stringa text fino ad esaurirli e tornare nil. Molte funzioni iteratrici agiscono proprio in questa maniera.
  • È possibile mantenere i conteggi separati per funzioni iteratrici, utilizzando variabili differenti. L'istruzione q = mw.ustring.gmatch( text, "(.)" ) estrarrà caratteri dalla stessa stringa dell'esempio precedente valutando d = q() senza che questo modifichi il comportamento di a().
  • Le funzioni da chiamare col comando {{#invoke|...}} sono abitualmente definite nella forma p.myFunctionName, dove p è la tabella che viene restituita dal modulo. Altre funzioni saranno locali e possono avere qualunque nome valido, ma non saranno accessibili dall'esterno.

Moduli di supporto[modifica | modifica wikitesto]

Sono disponibili alcuni moduli di supporto per lo sviluppo di moduli e template:

Modulo:Arguments
Semplifica la gestione dei parametri passati da #invoke. Principalmente rimuove gli argomenti vuoti ed elimina gli spazi dall'estremità degli argomenti, legge gli argomenti dal frame corrente e dal frame padre. Sono possibili diverse personalizzazioni del suo comportamento.
Modulo:No globals
Verifica che il modulo in cui è richiamato non legga variabili globali nulle e non ne crei di nuove, ad eccezione della variabile "arg" (è necessaria a Scribunto, vedere sopra). È utile per individuare errori di programmazione.
Modulo:Controllo parametri sconosciuti
Aggiunto in fondo a un template, permette di verificare che sia richiamato solo dai parametri previsti dal template stesso.
Modulo:String
Permette di utilizzare nei template funzioni di manipolazione delle stringhe (calcolare la lunghezza, verificare che una stringa sia contenuta in un'altra), sostituire caratteri accentati con i corrispondenti non accentati, rimpiazzare una stringa con un'altra.

Pagine correlate[modifica | modifica wikitesto]