Etichette: Modifica da mobile Modifica da web per mobile |
→Suggerimenti di stile: Per chi usa la versione mobile Etichette: Modifica da mobile Modifica da web per mobile |
||
Riga 91: | Riga 91: | ||
== Suggerimenti di stile == |
== Suggerimenti di stile == |
||
* Usare il [[tabulatore]] per l'[[indentazione]]. |
* Usare il [[tabulatore]] (8 spazi) 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 <code>if</code> dovrebbero essere piazzate su una linea successiva. |
* 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 <code>if</code> dovrebbero essere piazzate su una linea successiva. |
||
* Evitare spazi inutili nelle chiamate di funzioni e tabelle o prima o dopo le parentesi di apertura (<code>[, (, {</code>) e di chiusura (<code>], ), }</code>). |
* Evitare spazi inutili nelle chiamate di funzioni e tabelle o prima o dopo le parentesi di apertura (<code>[, (, {</code>) e di chiusura (<code>], ), }</code>). |
Versione delle 22:56, 26 feb 2018
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 Teknopedia.
Se non sei interessato alla programmazione, ma solo all'uso di moduli già scritti, consulta le pagine correlate.
Generalità
Lua è un linguaggio di programmazione implementato su Teknopedia con alcune sostanziali restrizioni mediante Scribunto. Il suo scopo è permettere di processare i dati disponibili sulle pagine di Teknopedia per organizzarne in maniera personalizzata la visualizzazione.
La documentazione principale di Teknopedia 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 Teknopedia.
Creare un modulo di prova
Dato che i moduli funzionano solo nell'omonimo namespace, esiste la pagina Modulo:Sandbox per le prove (analogamente a Teknopedia: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
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
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 Teknopedia 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
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 Teknopedia 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 Teknopedia mediante il
-- comando #invoke.
-- L'argomento "frame" conterrà i dati che Teknopedia invia a questa funzione quando viene
-- chiamata.
function p.hello( frame )
-- L'istruzione successiva termina la funzione e ritorna la stringa "HelloWorld" a Teknopedia.
-- 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 Teknopedia.
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
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 Teknopedia 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 Teknopedia è 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
- Se la funzione
len
del modulo:String viene chiamata con{{#invoke:String|len|Pippo}}
, alloraframe.args[1]
conterrà la stringa "Pippo". - Con l'istruzione
{{#invoke:HelloWorld|hello_nome1|Pippo|come va}}
verrà richiamata la funzionehello_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 istruzioniframe.args[1]
eframe.args[2]
.
Parametri nominali
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
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
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.
Suggerimenti di stile
- Usare il tabulatore (8 spazi) 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
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
sea
ènil
o la concatenazionea .. b
se una delle due ènil
. È indispensabile inizializzare le variabili con dei valori comelocal a = ""
olocal a = {}
. In assenza di una variabile inizializzata conlocal
, viene spesso utilizzato ancheglobal
. - string expected, got function. Alcune funzioni come
mw.ustring.gmatch
ritornano funzioni e non stringhe.
Concetti base
- 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}}
alloraa[1] = 1
,a[2] = "quotation"
,a[3]
equivale al valore restituito dalla funzionegmatch
ea[4]
è la tabella{2, 3, 4}
. Una lista di espressioni può essere recuperata da una tabella con l'istruzioneunpack()
:b, c, d = unpack(a)
restituiràb = 1
,c = "quotation"
ed
alla funzione. - Una tabella è una sequenza supportata opzionalmente da chiavi con nome, per esempio
digit["two"] = "2"
. Va però ricordato che diverse funzioni cometable.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
- 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à ada
una funzione e non il valore di una stringa. In questo caso la funzione ritornerà ad ogni chiamata uno dei caratteri della stringatext
fino ad esaurirli e tornarenil
. 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 valutandod = q()
senza che questo modifichi il comportamento dia()
. - Le funzioni da chiamare col comando
{{#invoke|...}}
sono abitualmente definite nella formap.myFunctionName
, dovep
è la tabella che viene restituita dal modulo. Altre funzioni saranno locali e possono avere qualunque nome valido, ma non saranno accessibili dall'esterno.