venerdì 13 gennaio 2012

F# - Ennuple

Molto spesso programmando in qualsiasi linguaggio si verifica la necessità di raggruppare più variabili, anche di tipo diverso, che magari descrivono le caratteristiche di un determinato oggetto o soggetto. F# propone una soluzione molto semplice a questo problema, utilizzando le così dette ennuple.
Esse, in pratica, sono un raggruppamento di due o più valori, anche di tipo diverso. Molto spesso le ennuple vengono usate come l'insieme dei parametri da passare ad una funzione. Per esempio, se vogliamo che nel momento in cui viene richiamata la nostra funzione vengano passati tutti i parametri assieme, basta usare una ennupla come argomento della funzione. Ma prima di scendere in dettagli vediamo come possono essere create ed utilizzate le ennuple in F#:

let ennupla = (65,'A');;
let annedate = (ennupla,(1,3),12);;

Come si può vedere dal codice, una ennupla viene creata utilizzando le parentesi tonde e separando ogni elemento dall'altro mediante la virgola. Nella prima riga di codice vediamo una coppia formata da un numero intero e un carattere. Con la seconda riga di codice, invece, abbiamo creato un'ennupla formata da 3 elementi, di cui il primo non è altro che la coppia dichiarata in precedenza, il secondo elemento anch'esso è una coppia, però questa volta di interi, mente il terzo elemento è un intero. E qui abbiamo visto che le ennuple possono essere annidate e lunghe quanto vogliamo, però una volta create non possono modificare la dimensione e il tipo degli elementi. 
Vediamo un semplice esempio di come possono essere impiegate le ennuple. Supponiamo di voler scrivere una funzione, che restituisce il risultato di una equazione di secondo grado, noti a, b e c. In quanto una equazione di secondo grado può avere al massimo 2 soluzioni, dobbiamo per forza restituire una coppia di valori e quindi useremo le ennuple per la scrittura della funzione:

let soluzioni (a:float) (b:float) (c:float) =
    let d = b*b - 4.0*a*c in
    match d with
    d when d<0.0 -> failwith "l'equazione non ha soluzioni in R"
    | 0.0 -> ((-b-sqrt(d))/(2.0*a),(-b-sqrt(d))/(2.0*a))
    | d when d>0.0 -> ((-b-sqrt(d))/(2.0*a),(-b-sqrt(d))/(2.0*a));;

Proviamo ad esaminare il codice appena proposto. In pratica, abbiamo creato una funzione, che prende tre argomenti di tipo float. In questo caso abbiamo forzato il tipo dei parametri, per non dover di seguito convertire ogni volta il tipo delle variabili, inoltre in questo modo otteniamo un valore più esatto. Un'altra novità che introduce questo codice è la dichiarazione di una variabile locale nella funzione. Ciò è stato fato utilizzando la solita parola chiave let, seguita dalla dichiarazione del nome, dopodiché segue la parola chiave in, che indica la fine della dichiarazione. Dopo aver introdotto il nuovo nome, che abbiamo chiamato d, abbiamo attribuito ad esso il valore del discriminante dell'equazione.
Utilizzando il pattern matching abbiamo definito i tre casi, ovvero quando d>0, quando d<0 e quando d=0.
Nel caso in cui d<0 verrà generata un'eccezione, ovvero un messaggio in output, che indicherà che l'equazione con quei parametri non ha soluzione dell'insieme dei reali. Questa decisione è stata presa perché una funzione può restituire un valore di un solo tipo e non sarebbe molto corretto restituire una coppia di reali. 
Se il discriminante, invece, vale 0, allora l'equazione ha un'unica soluzione, o meglio, le due soluzioni coincidono, per cui restituiamo una coppia di numeri float uguali.
Finalmente, nel caso in cui d>0 l'equazione ha due soluzioni, per cui viene restituita rispettivamente una coppia di numeri float. Per il calcolo delle soluzioni è stata utilizzata, inoltre, la funzione sqrt, una funzione predefinita di F#, che serve per calcolare la radice quadrata di un numero float.
Se proviamo a vedere lo stampo di questa funzione, eseguendo il codice in alto, utilizzando l'interprete di F#, otterremo il seguente output:

val soluzioni : float -> float -> float -> float * float

Come possiamo vedere, eseguendo il codice viene introdotta una nuova funzione, chiamata soluzioni, che prende tre argomenti di tipo float. Come risultato essa restituisce una coppia di float e visto che F# è un linguaggio che ha un forte legame con il linguaggio matematico, l'insieme delle soluzioni viene rappresentata come il prodotto dell'insieme dei reali per se stesso, ovvero float*float.

Nessun commento:

Posta un commento