Basandosi sul seguente tipo di dato:
datatype espressione = costante of int
| somma of espressione * espressione
| sottrazione of espressione * espressione
| prodotto of espressione * espressione
| divisione of espressione * espressione;
scrivere una funzione Standard ML, chiamata eval,
che ha tipo espressione -> int.
Come suggerito dal nome, eval valuta l'espressione
ricevuta come argomento, ritornando un intero che indica il
risultato finale della valutazione.
La funzione eval deve essere definita in un file .sml
separato dalla
definizione del tipo di dato espressione.
Si consegni il file .sml contenente
la definizione di eval.
Questa e' una possibile soluzione.
E' possibile definire una funzione semplifica che semplifica
un'espressione ricevuta come argomento. La differenza fra
semplifica ed eval e' quindi che semplifica
ha tipo espressione -> espressione. Quindi, semplifica
puo' essere definita basandosi su eval (e magari
"nascondendo" eval tramite un costrutto local).
Questo approccio puo' essere implementato anche in modo molto piu' semplice.
E' pero' anche possibile
definire semplifica per via ricorsiva,
senza riferimenti ad eval.
Basandosi sul tipo di dato espressione e la funzione eval
definiti come segue:
datatype espressione = costante of int
| somma of espressione * espressione
| sottrazione of espressione * espressione
| prodotto of espressione * espressione
| divisione of espressione * espressione;
val rec eval = fn costante n => n
| somma (a1, a2) => (eval a1) + (eval a2)
| sottrazione (a1, a2) => (eval a1) - (eval a2)
| prodotto (a1, a2) => (eval a1) * (eval a2)
| divisione (a1, a2) => (eval a1) div (eval a2);
il tipo espressione puo' essere esteso come segue per supporare
il concetto di variabile:
datatype espressione = costante of int
| variabile of string
| somma of espressione * espressione
| sottrazione of espressione * espressione
| prodotto of espressione * espressione
| divisione of espressione * espressione
| var of string * espressione * espressione;
Si riscriva la funzione eval per supportare i due nuovi costruttori
variabile e var. variabile x, con
x di tipo stringa, e' valutata al valore della variabile di nome
x (per fare questo, eval deve cercare nell'ambiente
un legame fra tale nome ed un valore). var (x, e1, e2) e' valutata
al valore di e2 dopo aver assegnato ad x il valore di
e1.
Per poter valutare correttamente variabile e var,
eval deve quindi ricevere come argomento l'ambiente in cui valutare
le variabili. Tale ambiente puo' essere rappresentato come una lista di coppie
(stringa, intero) ed avra' quindi tipo (string * int) list.
La funzione eval deve quindi avere tipo
(string * int) list -> espressione -> int.
La funzione eval deve essere definita in un file .sml
separato dalla
definizione del tipo di dato espressione.
Si consegni il file .sml contenente
la definizione di eval.
Questa e' una possibile soluzione. Si noti che
in questa soluzione la funzione cerca viene definita come
visibile a tutti, mentre sarebbe piu' opportuno renderla locale a
eval usando un costrutto let o local.