Laboratorio di Programmazione III 4 Settembre 2008 Esercizio 1

Transcript

Laboratorio di Programmazione III 4 Settembre 2008 Esercizio 1
Nome: ______________________
Matricola: _____________________
Parziale (Si/No): ______
Laboratorio di Programmazione III
4 Settembre 2008
Esercizio 1 (solo totale): Scrivere in Scheme o in Lisp una funzione nuplica che prende in input un
intero n (dove n >= 0) una lista di interi l (eventualmente anche la lista vuota) e restituisce in output la
lista l con gli elementi ripetuti n volte (per n=0 la lista in output è pari alla lista vuota).
esempio: (nuplica 3 ‘(1 2 2 3)) restituisce: (1 1 1 2 2 2 2 2 2 3 3 3)
Esercizio 2 (solo totale): Mostrare cosa stampa in output ML nel valutare le seguenti istruzioni.
NOTA: se non si ricorda la sintassi dei messaggi di output di ML è sufficiente specificare il risultato
della valutazione dell’istruzione (e.g., identificatore con valore 5, puntatore al valore 7, il numero 3,
funzione, etc.), e il tipo del risultato (e.g., int, puntatore a real, bool*int->real, etc.). In caso di errore,
specificare il motivo per cui la valutazione dell’istruzione ha terminato in un errore. In caso di non
terminazione, specificarne la causa. Ogni istruzione va valutata tenendo conto dell’ambiente modificato
dalle precedenti istruzioni.
val x = 3;
________________________________________
val y = ref (ref x);
________________________________________
let val z = y in let val y = ref (ref 4) and x = ref 2 in !x * !(!z) end end;
______________________________________________________________________
y;
________________________________________
fun g(k) = !(!y) * !k;
________________________________________
g(8);
________________________________________
fun dup(h) = ref (h(ref x)*2);________________________________________
dup(g);
________________________________________
Esercizio 3 (solo totale): Data le seguente definizione di tipo di dato astratto in ML:
datatype Grafo = arco of int * int | listaArchi of int * int * Grafo;
scrivere una funzione visit che prende in input un grafo G di tipo Grafo e ritorna in output una lista L
di interi dove gli elementi in L sono le etichette dei nodi contenuti in G e sono elencati secondo
l’ordine con cui compaiono, da sinistra verso destra, in G (si noti che la visit prende in input anche
una lista che serve per mantenere traccia dei nodi del grafo già visitati).
esempio: visit(listaArchi(4,3,listaArchi(3,4,listaArchi(4,2,
listaArchi(2,3,arco(3,1))))), []);
restituisce: [4,3,2,1]
Esercizio 4 (parziale e totale): Si dica quale è il tipo di ognuna delle seguenti dichiarazioni ML. Si
motivi la risposta in modo discorsivo senza ricorrere all’utilizzo dell’algoritmo di inferenza dei tipi.
1)
2)
3)
4)
5)
-
fun
fun
fun
fun
fun
a(x,y) = x+2*y;
b(x,y)=x+y/2.0;
c(f)= fn y => f(y);
d(f,x) = f(f(x));
e(x,y,b) = if b(y) then x else y;
Esercizio 5 (parziale e totale): Dato il seguente programma C++:
#include <iostream>
class B;
class A {
public:
virtual A* set(A* a) = 0;
};
class B : public A {
public:
virtual A* set(B* b) {
std::cout << "set1 has been called" << std::endl;
b = this;
return b;
}
virtual B* set(A* a) {
std::cout << "set2 has been called" << std::endl;
a = this;
return this;
}
};
int main(int argc, char *argv[]) {
B *b = new B();
A
a
a
a
*a = b->set(b);
= b->set(a);
= a->set(b);
= a->set(a);
return 0;
}
dire se esso può essere correttamente compilato ed eseguito, oppure no. Nel caso di errore, se ne
spieghi la causa. Nel caso in cui si riscontri che il programma è corretto, si scriva quale sarà il suo
output motivando opportunamente la risposta per ognuna delle quattro chiamate alla set che vengono
effettuate nel main.
Esercizio 6 (solo parziale): Data la seguente dichiarazione di funzione in ML:
=
=
=
=
fun g(h,nil) = nil |
g(h, a::l) = let fun f(a,nil) = a::nil |
f(a, b::l) = if h(a,b) then a::(b::l) else b::f(a,l)
in f(a,g(h,l))
end;
quale è il tipo della funzione g. Si motivi la risposta in modo discorsivo
dire
senza ricorrere all’utilizzo
dell’algoritmo di inferenza dei tipi (nel farlo si fornisca anche il tipo della funzione f).
Esercizio 7 (solo parziale): Le seguenti funzioni ML, essenzialmente, hanno lo stesso comportamento
a run-time nel senso che se si osserva la loro esecuzione non si notano differenze nell’esecuzione di
una rispetto all’esecuzione di un’altra.
- fun f(x) = f(x) andalso f(x);
- fun g(x) = g(x) * 2;
Ad esempio, se consideriamo il programma ML f(3), qualsiasi cosa faccia questo programma, il
programma ML g(3) (ottenuto sostituendo g con f) fa esattamente la stessa cosa. In particolare, se il
primo programma non genera un errore a run-time neanche il secondo lo farà. Data questa premessa, si
risponda alle seguenti domande:
(a) Quale è il tipo di f?
(b) Quale è il tipo di g?
(c) Si spieghi informalmente perché queste due funzioni hanno lo stesso comportamento
osservabile a run-time.
(d) Siccome le due funzioni sono equivalenti (dal punto di vista del loro comportamento
osservabile a run-time), potrebbe essere opportuno dare loro lo stesso tipo. Perché i progettisti
di ML non hanno lavorato più duramente per fare in modo che l’algoritmo di inferenza dei tipi
avesse potuto assegnare lo stesso tipo a f e a g? E’ stato un errore o una mancanza dei
progettisti? Motivare in modo opportuno le risposte.