Funzioni definite dall'utente (UDF) |
Le funzioni definite dall'utente permettono di espandere il linguaggio Proteus, per includere nuove funzionalità evolute; se definite all'interno del file di programma (oppure incluse con !include), possono essere utilizzate esattamente allo stesso modo delle funzioni di libreria.
Le UDF possono restituire qualsiasi valore: stringhe, interi, numeri in virgola mobile. I nomi delle UDF seguono le stesse limitazioni indicate per gli identificatori.
Per definire una UDF, si utilizza il metodo FUNCTION, con la seguente sintassi:
FUNCTION Funzione([@]par1[,[@]par2[,[@]par3 ..]]) [metodi] RETURN [expr]
Ogni UDF può avere 0 o più parametri, che assumono i valori delle espressioni passate alla funzione al momento della chiamata. É possibile accedere alle variabili "esterne" attraverso la funzione PUB (oppure il prefisso "_") ed impostare i relativi valori con PSET, oppure utilizzare il passaggio per riferimento implicito o esplicito.
PUB prende come unico parametro il nome di un identificatore (letterale, non tra virgolette) e corrisponde all'impiego del nome di identificatore al di fuori della funzione; esso dovrebbe comparire, quindi, solo in una UDF, come PSET.
Tutti gli identificatori che compaiono all'interno di una definizione di funzione sono locali ed invisibili all'esterno; essi non mantengono il loro valore tra invocazioni ripetute della funzione.
É possibile specificare più RETURN all'interno della definizione di una funzione, anche con espressioni di tipo diverso; il primo RETURN fuori da strutture condizionali e da cicli termina la definizione di funzione.
Es.
FUNCTION MyFact(n) IF LT(n, 1) ; Questo RETURN non termina la definizione, perché dentro un IF RETURN 1 FI ; Questo RETURN termina la definizione RETURN MUL(n, MyFact(DEC(n)))
Due particolari UDF sono ONSTART e ONEND; esse, qualora definite, sono eseguite una sola volta rispettivamente prima dell'esecuzione del programma vero e proprio e al termine, prima dell'uscita regolare (cioé non conseguente all'esecuzione del metodo ABORT). Esse non devono avere alcun parametro, ma per il resto possono fare qualsiasi cosa è ammessa nelle altre UDF, inclusa l'invocazione di altre funzioni definite dall'utente. In queste UDF le variabili sono di norma impostate con PSET e lette con PUB, in quanto ONSTART è utilizzata per lo più per inizializzare delle variabili a valori diversi da 0 e ONEND è impiegata per stampare i risultati dell'elaborazione.
É proibito l'uso del metodo IGNORE all'interno di una funzione.
É possibile utilizzare delle UDF prima di averle definite, purché esse vengano definite prima della fine del programma.
Come conseguenza, le UDF possono anche essere ricorsive.
Proteus segnala un errore nel caso in cui:
Ogni funzione deve terminare restituendo un valore; nel caso il valore non sia importante, si può omettere ed in questo caso è assunto implicitamente "" (= 0 = 0.0); esempio:
RETURN
è equivalente a:
RETURN ""
Ecco, come esempio più articolato, cinque funzioni per simulare una matrice attraverso i vettori:
FUNCTION MatNew(row, col) ; Crea una matrice di row righe e col colonne hmat = VECNEW(row) FOR r = 1 TO row VECSET(hmat, r, VECNEW(col)) NEXT RETURN hmat FUNCTION MatLen(hmat) ; Restituisce il numero di elementi nella matrice (righe x colonne) RETURN MUL(VECLEN(hmat), VECLEN(VECGET(hmat, 1))) FUNCTION MatGet(hmat, row, col) ; Restituisce l'elemento row, col della matrice hmat RETURN VECGET(VECGET(hmat, row), col) FUNCTION MatSet(hmat, row, col, val) ; Imposta a val l'elemento row, col della matrice hmat RETURN VECSET(VECGET(hmat, row), col, val) FUNCTION MatFree(hmat) ; Libera la memoria riservata alla matrice hmat limit = VECLEN(hmat) FOR row = 1 TO limit VECFREE(VECGET(hmat, row)) NEXT RETURN VECFREE(hmat)
Come si può vedere, è molto semplice creare matrici multidimensionali in questo modo; un vantaggio di questa costruzione è la possibilità di creare strutture matriciali con righe di diversa lunghezza; inoltre, ogni elemento può essere una stringa o un numero (intero/in virgola mobile).
Inizio pagina | Prossimo argomento | Argomento precedente | Indice per argomenti | Indice analitico |