Docsity
Docsity

Prepare for your exams
Prepare for your exams

Study with the several resources on Docsity


Earn points to download
Earn points to download

Earn points by helping other students or get them with a premium plan


Guidelines and tips
Guidelines and tips

CSE 341 - Programming Languages Final Exam - Autumn 2012 - Answer Key, Exams of Programming Languages

The answer key for the final exam of the Programming Languages course (CSE 341) taken in Autumn 2012. The exam consists of six questions covering topics such as Haskell, Racket, Prolog, and MUPL. The questions require students to write functions, demonstrate macro hygiene, and identify errors in code. detailed answers and explanations for each question.

Typology: Exams

2011/2012

Uploaded on 05/11/2023

gail
gail 🇺🇸

4.9

(10)

222 documents

1 / 10

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
CSE 341 - Programming Languages
Final exam - Autumn 2012 - Answer Key
Total points possible: 134
1. (10 points) Write a Haskell function mapfns, and a type declaration for it (the most general type possible).
mapfns takes a list of functions and a list of items, and that returns a new list consisting of the result of
applying each function to the corresponding item. If there are a different number of functions and items, the
resulting list is the same length as the shorter of the two. Examples:
mapfns [(+1), (*2), sqrt] [2.0, 3.5, 4.0] => [3.0, 7.0, 2.0]
mapfns [(+1), (+1)] [1..] => [2, 3]
mapfns :: [t -> a] -> [t] -> [a]
mapfns (f:fs) (x:xs) = f x : mapfns fs xs
mapfns _ _ = []
2. (10 points) Write a Racket function twice that takes a list as an argument, and returns #t if there is at least
one adjacent repeated element in the list, and otherwise #f. You can assume that the argument is a proper list.
Use equal? to test whether one element is a repeat of the previous one. Examples:
(twice '()) => #f
(twice '(a b b c d e)) => #t
(twice '(a b c a b)) => #f
(define (twice s)
(cond ((null? s) #f)
((null? (cdr s)) #f)
((equal? (car s) (cadr s)) #t)
(else (twice (cdr s)))))
3. (8 points) Consider the my-or macro discussed in class. This works exactly the same as the built-in or macro
in Racket.
(define-syntax my-or
(syntax-rules ()
((my-or) #f)
((my-or e) e)
((my-or e1 e2 ...)
(let ((temp e1))
(if temp
temp
(my-or e2 ...))))))
It relies on macro hygiene. Demonstrate this by writing Racket code that would result in a wrong answer from
my-or if Racket didn’t have macro hygiene. Also say both what the correct answer is, and what the answer
would be if Racket didn’t have macro hygiene.
(let ((temp 3))
(or #f (= temp 3)))
1
pf3
pf4
pf5
pf8
pf9
pfa

Partial preview of the text

Download CSE 341 - Programming Languages Final Exam - Autumn 2012 - Answer Key and more Exams Programming Languages in PDF only on Docsity!

CSE 341 - Programming Languages

Final exam - Autumn 2012 - Answer Key

Total points possible: 134

  1. (10 points) Write a Haskell function mapfns, and a type declaration for it (the most general type possible). mapfns takes a list of functions and a list of items, and that returns a new list consisting of the result of applying each function to the corresponding item. If there are a different number of functions and items, the resulting list is the same length as the shorter of the two. Examples:

mapfns [(+1), (*2), sqrt] [2.0, 3.5, 4.0] => [3.0, 7.0, 2.0] mapfns [(+1), (+1)] [1..] => [2, 3]

mapfns :: [t -> a] -> [t] -> [a]

mapfns (f:fs) (x:xs) = f x : mapfns fs xs mapfns _ _ = []

  1. (10 points) Write a Racket function twice that takes a list as an argument, and returns #t if there is at least one adjacent repeated element in the list, and otherwise #f. You can assume that the argument is a proper list. Use equal? to test whether one element is a repeat of the previous one. Examples:

(twice '()) => #f (twice '(a b b c d e)) => #t (twice '(a b c a b)) => #f

(define (twice s) (cond ((null? s) #f) ((null? (cdr s)) #f) ((equal? (car s) (cadr s)) #t) (else (twice (cdr s)))))

  1. (8 points) Consider the my-or macro discussed in class. This works exactly the same as the built-in or macro in Racket.

(define-syntax my-or (syntax-rules () ((my-or) #f) ((my-or e) e) ((my-or e1 e2 ...) (let ((temp e1)) (if temp temp (my-or e2 ...))))))

It relies on macro hygiene. Demonstrate this by writing Racket code that would result in a wrong answer from my-or if Racket didn’t have macro hygiene. Also say both what the correct answer is, and what the answer would be if Racket didn’t have macro hygiene.

(let ((temp 3)) (or #f (= temp 3)))

Without macro hygiene, when the macro is expanded it uses a variable temp in the if expression. This will have the value #f, which shadows the binding of temp to 3. The expression should have the value #t,but without macro hygiene it would evaluate to #f.

  1. (8 points) Is MUPL statically typed? If it is, give a MUPL expression that has a type error that would be detected statically. If it is not, just say “no”. (For both this and the following question, you don’t need to remember the exact MUPL structs to build MUPL expressions; but if you’re not sure you’ve got the names correct say what they are and what they do so that we can grade these.) No. Is MUPL type-safe? If it is, give a MUPL expression that has a type error that would be detected dynamically. If it is not, give a MUPL expression that would be evaluated incorrectly due to the type error. As in the assignment, you should assume MUPL programs are syntactically correct, e.g., do not worry about wrong things like (int "hi") or (int (int 37)). Think of (int 3) as part of the program’s syntax its how you write the number 3 in MUPL. Yes, MUPL is type-safe. The assignment required including runtime type checking in functions. For example, this expression would give a runtime MUPL error: (fst (int 3)) The function fst gets the first element of a list, but we’re giving it an integer argument.
  2. (10 points) Consider a twice rule in Prolog, which looks for an element that occurs twice in a row in a list:

twice([X,X|Xs],X). twice([X|Xs],Y) :- twice(Xs,Y).

What are all the answers returned for the following goals? If there are an infinite number, say that, and include at least the first 3 answers.

(a) twice([1,2,2],B). Answer: B=2. (b) twice([1,2,2,1],B). Answer: B=2. (c) twice([1,2,3,2,1],B). Answer: false. (d) twice([1,2,2,2,3,1,1],B). Answers: B=2; B=2; B= (e) twice(As,1). Answers: As = [1, 1|X1]; As = [X1, 1, 1|X2] ; As = [X1, X2, 1, 1|X3]; .... (infinite number of answers – here X1 etc are going to be variable names that Prolog generates)

  1. (10 points) Now consider the twice rule again, but with cut:

twice([X,X|Xs],X) :- !. twice([X|Xs],Y) :- twice(Xs,Y).

What are all the answers returned for the following goals? (These are the same as for Question 5.) If there are an infinite number, say that, and include at least the first 3 answers.

(a) twice([1,2,2],B). Answer: B=2. (b) twice([1,2,2,1],B). Answer: B=2. (c) twice([1,2,3,2,1],B). Answer: false.

What are all the answers are returned for the goal ancestor(dolphin,X)? For full credit you need to write down the answers in exactly the order that your program will return them. The answer X=dolphin should be produced first, but after that you can return the answers in any order; duplicates are OK.

?- ancestor(dolphin,X). X = dolphin ; X = mammal ; X = animal ; X = object ; X = seacreature ; X = animal ; X = object ; false.

  1. (10 points) Consider the difference list version of reverse as given in the lecture notes:

reverse(Xs,Rs) :- reverse_dl(Xs,Rs[]).

reverse_dl([],T\T). reverse_dl([X|Xs],Rs\T) :- reverse_dl(Xs,Rs[X|T]).

Draw the derivation tree for the following goal:

?- reverse([a,b,c],R).

Please see the scan of the hand-drawn tree at the end of this pdf.

  1. (12 points) Consider the following Ruby classes and mixins.

class C def print_me "C1 print_me" end def test 1 end end

module M def print_me "M1 print_me" end def test 10+super end end

module M def print_me "M2 print_me" end def test

end end

class C2 < C include M end

class C3 < C include M1, M end

Now define variables c1, c2, and c3 as follows:

c1 = C1.new c2 = C2.new c3 = C3.new

What is printed as a result of evaluating the following expressions? (Remember that the value returned by a method is the value of the last expression, if there isn’t an explicit return.)

c1.print_me => "C1 print_me"

c2.print_me => "M1 print_me"

c3.print_me => "M1 print_me"

c1.test => 1

c2.test => 11

c3.test => 110

  1. (16 points) Define a Ruby class MySet that represents a set. (There’s already a built-in class Set — define your own however, rather than using the built-in one.) MySet should be a subclass of Object and should mix in Enumerable. Internally, it should use a Ruby array to hold its elements. As a reminder, a set is an unordered collection of elements, with no duplicates. The union of two sets A and B is a new set consisting of all elements that are in either A or B. The intersection of two sets A and B is a new set consisting of the elements that are in both A and B. MySet should define the following methods:

initialize Initialize this to be an empty set. add(element) Add an element to this set, if it’s not already a member. (This changes the set.) union(other) Return a new set that is the union of the receiver and other. This doesn’t change the set (no side effect).

a = new String[5]; b = a; a[0] = "oyster"; test(a,1); test(b,2); test( (Object[]) a, 3); test( (String[]) b, 4); for(int i = 0; i<a.length; i++) { System.out.print(a[i]); System.out.print(" "); } System.out.print("\n"); } public static void test(Object[] c, int i) { c[i] = "clam"; } public static void test(String[] c, int i) { c[i] = "squid"; } }

Executes without error - output is: oyster squid clam clam squid

/***************** Test2 *****************/ import java.util.LinkedList; class Test2 { public static void main(String[] args) { LinkedList a; LinkedList b; a = new LinkedList(); b = a; a.addFirst("oyster"); test(a,1); test(b,2); for (String s : a) { System.out.print(s); System.out.print(" "); } System.out.print("\n"); } public static void test(LinkedList c, int i) { c.add(i,"clam"); } public static void test(LinkedList c, int i) { c.add(i,"clam"); } }

Doesn't compile - there are type errors:

Test2.java:21: test(java.util.LinkedList<java.lang.Object>,int) is already defined in Test public static void test(LinkedList c, int i) { ˆ Test2.java:8: incompatible types found : java.util.LinkedList<java.lang.String> required: java.util.LinkedList<java.lang.Object> b = a; ˆ Test2.java:10: test(java.util.LinkedList<java.lang.Object>,int) in Test2 cannot be applied to (java.util.LinkedList<java.lang.String>,int) test(a,1); ˆ 3 errors

These errors are all because LinkedList is not a subtype of LinkedList.

class Test3 { public static void main(String[] args) { String[] a; Object[] b; a = new String[2]; b = a; a[0] = "oyster"; System.out.println("added an oyster"); b[1] = new Integer(5); System.out.println("added an integer"); for(int i = 0; i<a.length; i++) { System.out.print(a[i]); System.out.print(" "); } System.out.print("\n"); } }

Compiles, but gets a runtime exception:

added an oyster Exception in thread "main" java.lang.ArrayStoreException: java.lang.Integer at Test3.main(Test3.java:9)

  1. (10 points) True or false?

(a) A Haskell expression of type IO t can never occur inside another expression of type (Num t) => [t]