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.