=========================preview======================
(COMP251)COMP251_01F-final_sol.pdf
Back to COMP251 Login to download
======================================================
COMP251 Fall 2001 Final Exam Solution
Part I
1.
C

2.
D

3.
D

4.
E

5.
E

6.
B

7.
A



Part II
Problem 1
(In general, you get credits for saying right things, and you do not get penalized for saying things that are not correct.)
(a)
Macro expansion is more efficient since it does not require AR to implement it, and is done before compiling. Macro expansion is of limited use since it cannot handle recursion. Common mistake: a lot of people mentioned about name conflicts and side effects. While they treat name conflicts differently, it is hard to say which one is better. Side effects are more of the consequence of assignment and pointers than parameter passing methods. Some people also mentioned that macro expansion does not do type checking. While this is true for C and C++, one can easily implement a macro expansion with type checking. A few mentioned that macro expansion will increase the size of the final compiled code. This is true, so you get partial credit for this. A few also mentioned that procedure call, compared with macro expansion, leads to better programming methodology. You also get partial credit for saying this only.

(b)
Computing by relation is more flexible since it does not have a built-in distinction of input and output. Common mistake: quite a few mentioned that LP is weak typed, so is more flexible than FP which is strongly typed. Actually types have nothing to do LP and FP. There are LP languages which are strongly typed as well. There are also FP languages which are weakly typed. In fact, the first FP language, Lisp, has no types at all. There are quite a few who mentioned that LP allows one to get multiple answers from a query

-you get 1 pt for saying this alone.

(c)
Because in SML, every expression must have a unique TYPE, so it is impossible to have if-then given the type structures in SML.

(d)
Common mistake: a lot of people mentioned each expression must return a value. But this does not necessarily rule out if-then: when the condition is false, we can assume the expression will have, say value (). But you get partial credit (1pt) for saying this alone without mentioning types.


Problem 2
(a)
2
2
0
3


(b)
3
1
-1
3


(c)
0
1
2
3




Problem 3
(a)
val it = true : bool

(b)
val it = false : bool


(c) Error: operator and operand don't agree
Problem 4
val truth_value = fn : bool -> int val foo = fn : ('a -> 'b) -> 'a -> 'b
Problem 5
(,) (,)
/ \ / \
/ \ / \
nil :: nil ::

/ \ / \_________________
/ \ / \
:: z :: z= ::
/ \ / \_____ / \
/ \ / \ / \

x y x= cons y= :: :: nil / \ / \ / \ / \ / \ / \ 4 cons empty nil empty nil / \/ \ 3 empty
Problem 6
val rd = fn : ('a -> 'b -> 'b) -> 'b -> 'a list -> 'b val cons = fn : 'a -> 'a list -> 'a list val it = [4,2,5,1,2,3] : int list
r1: min(A,B,M) :- !, A<B, M=A. r2: min(A,B,M) :- M=B.
marking scheme for Q7
(a)
? X= [1,2,3], member(a, X