# Funzioni definite dall'utente

## Introduzione

A partire dalla versione 1.4.0, gretl contiene un nuovo meccanismo per definire funzioni all'interno di uno script. Si noti che il nuovo modo di definire le funzioni presenta aspetti non compatibili con la versione 1.3.3 del programma.

## Definizione di una funzione

Occorre definire una funzione prima di poterla utilizzare. La sintassi per farlo è la seguente:

          function nome-funzione parametri
             corpo della funzione
          end function

Il nome-funzione identifica la funzione in modo univoco: deve iniziare con una lettera, può essere lungo al massimo 31 caratteri (eventuali caratteri in più verranno troncati) e non può contenere spazi. Se si tenta di definire una funzione con lo stesso nome di un comando di gretl o di una funzione preesistente, si otterrà un'errore. Nel secondo caso, per evitare un errore (ossia per poter ridefinire una funzione utente), basta far precedere la definizione della funzione da:

          function nome-funzioneclear

I parametri di una funzione (se esistono) vanno indicati sotto forma di lista separata da virgole. I parametri possono essere di tre tipi: variabili ordinarie (serie di dati), variabili scalari, o liste di variabili. Ogni elemento della lista di parametri è composto da due termini: per prima cosa un indicatore di tipo (`series`, `scalar` o `list`), quindi il nome con cui il parametro verrà riconosciuto all'interno della funzione. Ecco un esempio (le parentesi che racchiudono la lista dei parametri sono opzionali):

          function funzione (series y, list xvars, scalar verbose)

Quando una funzione viene chiamata, i parametri vengono istanziati usando gli argomenti indicati nella chiamata della funzione. Vengono fatti dei controlli automatici per assicurarsi che il numero degli argomenti contenuti in una chiamata di funzione corrisponda al numero di parametri, e che i tipi degli argomenti corrispondano ai tipi specificati nella definizione della funzione; se qualcuna di queste condizioni è violata, viene segnalato un errore. Una serie può essere indicata come argomento specificando il nome della variabile in questione, oppure il suo numero identificativo. Gli scalari possono essere indicati specificando il nome di una variabile o un valore numerico (non è possibile indicare il numero identificativo della variabile). Le liste devono essere indicate per nome.

Il corpo della funzione è composto da comandi gretl o funzioni definite dall'utente (ossia, le funzioni possono essere nidificate). Una funzione può persino chiamare sé stessa (ossia, le funzioni possono essere ricorsive), fino a un massimo di 8 livelli di ricorsività, ma questo valore è provvisorio, potrà essere aumentato se sembra troppo restrittivo. Se il corpo della funzione può contenere chiamate ad altre funzioni non può però contenere definizioni di altre funzioni, ossia non è possibile definire una funzione all'interno di un'altra funzione.

Le funzioni possono essere chiamate, ma non definite, all'interno di un loop (si veda il ).

## Chiamare una funzione

Una funzione utente viene chiamata, o invocata, usando il suo nome, eventualmente seguito da argomenti; se si usano due o più argomenti, vanno separati da virgole. L'esempio seguente mostra una chiamata di funzione che rispetta la definizione della funzione stessa.

          # Definizione della funzione
          function ols_ess (series y, list xvars)
            ols y 0 xvars --quiet
            scalar myess = $ess
            printf "ESS = %g\n", myess
            return scalar myess
          end function
          # Script principale
          open data4-1
          list xlist = 2 3 4
          # Chiamata della funzione (il valore restituito viene qui ignorato)
          ols_ess price, xlist

La chiamata della funzione contiene due argomenti: il primo è una serie di dati specificata per nome, e il secondo è una lista di regressori. Si noti che la funzione produce la variabile `myess` come risultato, ma in questo esempio esso è ignorato.

(Una nota a margine: se si desidera che una funzione calcoli alcuni valori che hanno a che fare con una regressione, ma non si è interessati ai risultati completi della regressione, è possibile usare l'opzione `--quiet` con il comando di stima, come visto sopra.)

Un secondo esempio mostra una chiamata di funzione che assegna i valori prodotti dalla funzione a variabili:

          # Definizione di funzione
          function ess_uhat (series y, list xvars)
            ols y 0 xvars --quiet
            scalar myess = $ess
            printf "ESS = %g\n", myess
            series uh = $uhat
            return scalar myess, series uh
          end function
          # Script principale
          open data4-1
          list xlist = 2 3 4
          # Chiamata di funzione
          (SSR, resids) = ess_uhat price, xlist

## Ambito delle variabili

Tutte le variabili create in una funzione sono locali a quella funzione, e vengono distrutte quando la funzione termina la sua esecuzione, a meno che esse siano rese disponibili come valori di ritorno, e che questi siano raccolti o assegnati nella chiamata della funzione.

Le funzioni non hanno accesso alle variabili nell'ambito esterno (ossia le variabili che esistono nello script da cui la funzione è chiamata), a meno che queste siano passate esplicitamente alla funzione come argomenti. Anche in questo caso, quello che viene passato alla funzione è una copia delle variabili in questione, quindi le variabili nell'ambito esterno non vengono mai modificate da una funzione, a meno che non vengano assegnate come valore prodotto da una funzione.

## Valori di uscita

Le funzioni possono produrre zero o più valori di uscita: questi possono essere serie o scalari (non liste). I valori di uscita sono specificati con una dichiarazione all'interno del corpo della funzione che comincia con la parola chiave `return`, seguita da una lista separata da virgole, ogni elemento della quale è composto da un indicatore di tipo e dal nome di una variabile (in modo analogo a quanto avviene per la lista dei parametri di una funzione). All'interno di una funzione può esserci solo una di queste dichiarazioni. Ecco un esempio di dichiarazione return valida:

          return scalar SSR, series resid

Si noti che la dichiarazione `return` non indica alla funzione di produrre il valore (terminare) nel punto in cui essa appare nel corpo della funzione. Piuttosto, essa specifica quali variabili sono disponibili per l'assegnazione quando la funzione terminerà, cosa che può avvenire solo quando: a) viene raggiunta la fine del codice che definisce la funzione; b) si incontra una dichiarazione `funcerr` (si veda oltre); c) gretl produce un errore.

La parola chiave `funcerr`, che può essere seguita da una stringa contenuta fra virgolette doppie, fa terminare una funzione con un messaggio di errore, che può essere generico o rappresentato dalla stringa indicata.

## Controllo degli errori

Quando gretl legge e compila una definizione di funzione, esegue un controllo degli errori minimale: controlla che il nome della funzione sia accettabile e che non si tenti di definire una funzione all'interno di una funzione (si veda ). Se il corpo della funzione contiene comandi non validi, verrà segnalato solo quando la funzione viene chiamata.