OCaml: le funzioni

Per definire una funzione la sintassi prevede il costrutto ‘let’ seguito dal nome della funzione, dai parametri indicati nel modo (nome:tipo) e, dopo il segno di uguaglianza il body della funzione e i soliti ;; finali.
Esempio:

# let areaRett (base:int) (altezza:int) = base*altezza;;
val areaRett : int -> int -> int = fun
# areaRett 4 7;;
- : int = 28
#

la riga

val areaRett : int -> int -> int = fun

indica che la funzione areaRett deve essere chiamata con 2 argomenti, entrambi interi e che il valore che essa restituisce è ancora un valore intero. L’esempio qui sopra si dice che è una applicazione della funzione areaRett agli argomenti 4 e 7. Come si vede gli argomenti possono essere passati direttamente senza essere racchiusi ad esempio tra parentesi, anche se il mettere le parentesi non è errore. Infatti

# areaRett (4) (7);;
- : int = 28

In realtà nella definizione della funzione non è necessario indicare in modo esplicito il tipo di parametri in quanto OCaml è in grado di determinarlo in base all’operatore che gli viene applicato o da cui sono legati. Ad esempio:

# let areaRett (base) (altezza) = base * altezza;;
val areaRett : int -> int -> int = fun
# areaRett 10 3;;
- : int = 30

# let areaRett (base) (altezza) = base *. altezza;;
val areaRett : float -> float -> float = fun
# areaRett 2.3 2.0;;
- : float = 4.6

L’operatore *. (asterisco punto) è l’operatore per la moltiplicazione di dati di tipo float che quindi è diverso dal normale operatore di moltiplicazione di interi *
Se provo ad usarlo con degli interi ovviamente mi viene segnalato un errore

# areaRett 5 4;;
Characters 9-10:
areaRett 5 4;;
^
This expression has type int but is here used with type float

Quindi a seconda dell’operatore indicato OCaml è in grado di stabilire di che tipo devono essere i parametri e quindi se accettare o meno quelli inseriti dall’utente. Questo potente meccanismo prende il nome di inferenza di tipo.

In realtà le parentesi si possono omettere e quindi la definizione finale sarà

# let areaRett base altezza = base * altezza;;
val areaRett : int -> int -> int = fun
# areaRett 3 5;;
- : int = 15

Esiste poi un altro metodo di definire una funzione del genere che consiste nel passargli una tupla (approfondirò il discorso tupla) di argomenti invece che i vari argomenti separatamente.

# let areaRett (base,altezza) = base * altezza;;
val areaRett : int * int -> int = fun
# areaRett (4,6);;
- : int = 24

La notazione int * int indica una tupla composta da 2 campi di valore intero. In questo caso la sintassi deve essere esattamente questa, con i parametri racchiusi tra parentesi tonde e separati tra loro da una virgola. Non è possibile passarli in modo diretto e neanche, ad esempio, separati da virgola ma senza parentesi.

# areaRett 4 6;;
Characters 0-8:
areaRett 4 6;;
^^^^^^^^
This function is applied to too many arguments,
maybe you forgot a `;'

# areaRett 4,6;;
Characters 9-10:
areaRett 4,6;;
^
This expression has type int but is here used with type int * int

This entry was posted in $1$s. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *