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
.