Unformatted text preview: 2002 Spring CS 61A Final — 2002-05-23 @ 12:30 – 15:30 Your name Circle your TA’s name
Chris Cheng Chris Karlof David Schultz Donald Chai Erwin Vedar Ryan Stejskal login: cs61aSeema Moorjani Todd Segal Yaping Li The student sitting to my right is The student sitting to my left is Question 0 (1 point): Fill out this front page correctly and put your name and login correctly at the top of each of the following pages. This exam is worth 90 points, 30% of your total course grade. It contains ﬁve short questions and four long questions. This booklet contains twelve numbered pages including the cover page. Put all answers on these pages, please; don’t hand in stray pieces of paper. This is an open book exam. For the short problems, you will receive negative points for wrong answers to multiple-choice questions (to compensate for guessing). It may be better to leave a question blank than to haphazardly guess the answer. However, your score for any single question will never drop below 0. When writing procedures, don’t put in error checks. Assume that you will be given arguments of the correct type. 0 S1 S2 READ AND SIGN THIS: I certify that my answers to this exam are all my own work, and that I have not discussed the exam questions or answers with anyone prior to taking this exam. If I am taking this exam early, I certify that I shall not discuss the exam questions or answers with anyone until after the scheduled exam time. S3 S4 S5 L1 L2 L3 L4 total 1
/1 /8 /8 /8 /7 /10 /12 /12 /12 /12 /90 Section I: Short Questions (estimated time: 1 hour for all 5 questions S1-S5) Question S1 (8 points) – Use the force, young Scheme Jedis... (a) Which of the 15 things they don’t oﬃcially teach you as a CS student was your favorite? (b) Which of the following interactions will execute faster, slower, or the same in the analyzing evaluator than in the original metacircular evaluator? Circle FASTER, SLOWER or SAME for each. > (define (gauss-recur n) ;; sum of #s from 1 to n (if (= n 1) 1 (+ n (gauss-recur (- n 1))))) > (gauss-recur 1000) > (define (gauss n) (/ (* (+ n 1) n) 2) > (gauss 1000) ;; sum of #s from 1 to n (Analyzing will be) FASTER SLOWER SAME (Analyzing will be) FASTER SLOWER SAME (c) For each evaluator, will the following expression return a value or cause an error? Circle VALUE or ERROR for each. > (let ((a 3) (b a)) (+ a 4)) VALUE ERROR The MCE VALUE ERROR Analyzing evaluator VALUE ERROR Lazy evaluator VALUE ERROR The MCE with dynamic scope (d) For each evaluator, will the following expression return a value or cause an error? Circle VALUE or ERROR for each. > (let ((a 3) (b a)) (+ a b)) ;; this line different from the one above VALUE ERROR The MCE VALUE ERROR Analyzing evaluator VALUE ERROR Lazy evaluator VALUE ERROR The MCE with dynamic scope 2 Your name Question S2 (8 points) – Please, mc-apply, don’t hurt ’em! login cs61a- (a) In the metacircular evaluator, mc-apply is not a higher-order procedure, even though it takes a procedure as its ﬁrst argument. This is because: (Check one) mc-apply is an underlying Scheme procedure, and its argument is a metacircular Scheme procedure. The arguments to mc-apply have already been evaluated. list-of-values is not a higher-order procedure. mc-apply is instead a universal function machine. The only higher-order procedures are map (or every), filter (or keep) and reduce (or accumulate). mc-eval and mc-apply employ mutual recursion. (b) Lem E. Tweakit makes the following change to mc-eval in the meta-circular evaluator: ((application? exp) (mc-apply (mc-eval (operator exp) env) (list (eval-sequence (operands exp) env)))) ;; <-- changed ;; was: (list-of-values (operands exp) env))) He ﬁnds that the modiﬁed evaluator doesn’t work correctly. Indicate which of the following expressions now cause an error, return incorrect results, or return the correct (usual) values. Circle ERROR, INCORRECT, or CORRECT for each. Assume square is deﬁnes as always: (define (square x) (* x x)). ERROR ERROR ERROR ERROR ERROR ERROR INCORRECT INCORRECT INCORRECT INCORRECT INCORRECT INCORRECT CORRECT CORRECT CORRECT CORRECT CORRECT CORRECT (square 1) (square 2) (+ 3 4) (lambda (x y) y) ((lambda (x y) y) 6 7) ((lambda (x) (+ x 5)) 9) 3 Question S3 (8 points) – Meatloaf sang “I (amb want need won’t-love) you” This question concerns continuations in the non-deterministic evaluator. Consider the following expression, which is typed at the ambeval prompt: > (* 2 (if (amb #t #f #t) (amb 3 4) 5)) (a) What are all the values we get before the evaluator responds with “No More Values” ? (b) When ambeval is called to evaluate (amb 3 4), it is given a success continuation. What does this success continuation do ﬁrst? (Check one) Print the words “;;; Amb-Eval value:” Print the value Multiply the value by 2 Check if the value is true Return 3 Return 4 Return 5 Call a failure continuation Evaluate (amb #t #f #t) Evaluate (amb #t #f) Evaluate (amb #t) Evaluate (amb) 4 Your name login cs61a- Question S4 (7 points) – Madonna sang: “We are living in a not-serial world” (a) Given the following deﬁnitions: > > > > (define (define (define (define s (make-serializer)) t (make-serializer)) (double-x!) (set! x (word x x))) (make-x-b!) (set! x ’b) ;; x -> xx ;; x -> b ...indicate what the possible ﬁnal values of x are. Circle any incorrect values. > (define x ’a) > (parallel-execute (s double-x!) (t make-x-b!) ) Values for x: (b) Assume the existence of three procedures, foo, bar, and baz, each of which modify a shared variable. We have three diﬀerent serializers s, t and u. For each of the following calls to parallel-execute, which might cause incorrect values and which might deadlock? Circle YES or NO for each question. > (parallel-execute (s foo) (t bar) ) (u baz) ) > (parallel-execute (s (t foo)) (t (u bar)) (s (u baz)) ) > (parallel-execute (s (s (t foo) (t bar)) (u (s baz))) ) Deadlock possible? Incorrect values? Deadlock possible? Incorrect values? Deadlock possible? Incorrect values? YES YES YES YES YES YES NO NO NO NO NO NO 5 Question S5 (10 points) – I’ll trade you my Ford PoS for your new Benz... We want to write swap-cars! which takes two lists and exchanges their ﬁrst two elements. For example: > (define numbers (list 1 2 3 4)) > (define letters (list ’a ’b ’c)) > (swap-cars! numbers letters) > numbers (a 2 3 4) > letters (1 b c) ;; numbers is (1 2 3 4) ;; letters is (a b c) (a) Which of the following will work? Circle YES or NO for each. It’s okay if they allocate new pairs, as long as the end result is what’s shown above. You may use the area to the right for scratch space. SCRATCH SPACE YES NO (define (swap-cars! x y) (let ((temp x)) (set! x (cons (car y) (cdr x))) (set! y (cons (car temp) (cdr y))))) (define (swap-cars! x y) (let ((temp (car x))) (set! (car x) (car y)) (set! (car y) temp))) (define (swap-cars! x y) (set-car! x (car y)) (set-car! y (car x))) (define (swap-cars! x y) (let ((temp x)) (set-car! x (car y)) (set-car! y (car temp)))) YES NO YES NO YES NO (b) For this last one, ﬁll in the blank so that swap-cars! works as advertised. (define (swap-cars! x y) (set! x (cons (car y) x)) (set-car! y (cadr x)) ;; Fill in the blank below with a call to ;; set!, set-car! or set-cdr! ( 6 )) Your name login cs61a- Section II: Longer Questions (estimated time: 30 minutes for each long question L1-L4) Question L1 (12 points) – Magical mystery procedure, step right this way! (define x ’a) (define y ’b) (define (double-x!) (set! x (word x x)) x) > (define (enclose-y!) (set! y (word ’< y ’>)) y) > (define (mystery f x y) (let ((y (f))) (enclose-y!) (word x y))) > > > ;; x becomes xx and is returned ;; y becomes <y> and is returned Draw two environment diagrams below, one for lexically scoped Scheme and the other for a dynamically scoped Scheme. Your diagram should result from evaluating the above deﬁnitions and the expression (mystery double-x! ’c ’d). Indicate the return value for both lexical and dynamic scope. To change the binding of a variable in a frame, cross out (don’t erase!) the old value and write the new one next to it. LEXICAL SCOPE > (mystery double-x! ’c ’d) | | | | | | | | | | | | | | | | | | | | | | | | 7 DYNAMIC SCOPE > (mystery double-x! ’c ’d) Question L2 (12 points) – The gamblers played ilo at the members-only club. (a) Write a query language program ilo (which stands for is-left-of) that will allow us to look for the items left of a certain element in a list. To help you, we’ve provided the helper program (member ?element ?list) which tests for list membership. E.g., the following are sample member and ilo queries. (We changed “;; Query input” to “Q>” for brevity): Q> (member 4 Q> (member 7 (member 7 (5 (5 7 2)) (5 7 2)) 7 2)) ;; Is 4 a member of (5 7 2)? Nope. ;; Is 7 a member of (5 7 2)? ;; Yesiree! Q> (?x ilo 3 in (5 7 3 8 2)) ;; We don’t care about the output order (5 ilo 3 in (5 7 3 8 2)) (7 ilo 3 in (5 7 3 8 2)) (b) For the following query, show the expected results. If you believe the query... • goes into an inﬁnite loop and either never returns or prints out an inﬁnite stream of matches, write INFINITE. • ﬁnds no matches and returns nothing, write NOTHING. • causes an internal error in the query system, write ERROR • ﬁnds a ﬁnite stream of matches, write them down. Q> (assert! (1 ilo 2 in (2 1))) Q> (?x ilo ?y in (2 1 1)) ;; Someone adds this incorrect assertion (c) Finally, let’s simulate uniﬁcation with an initial empty frame. Show your work and ﬁll in the blanks with all the bindings after uniﬁcation of the two patterns. If a variable is free (i.e., has no bindings), write FREE. If you believe the uniﬁer fails, write FAIL in the blanks. You should continue to substitute / unify so that your answers (if there are any) have as few remaining variables as possible. Unify... with... ( ?x ?x ) ( (?a ?b . ?c) (?c ?b)) ) ?a: ?b: 8 ?c: ?x: Your name login cs61a- Question L3 (12 points) – Row, row, row your boat, gently down the stream... You have seen how to use a single one-dimensional inﬁnite stream to enumerate a twodimensional inﬁnite set, as is done by pairs. The trouble is, pairs orders this stream in a strange way, and doesn’t include all of the points in the ﬁrst quadrant – only those with x ≤ y . We would like to create diagonal-pairs, an inﬁnite stream but which “slices” across the entire ﬁrst quadrant in diagonal strips. We’ll start by writing slice, which will generate these ﬁnite slices for us. The diagram on the left describes the ordering of the pairs in diagonal-pairs, and the examples on the right show calls to slice. > (show-stream diagonal-pairs) ((1 1) (2 1) (1 2) (3 1) (2 2) (1 3) (4 1) (3 2) (2 3) (1 4) ...) y^ +---+ 4 | 10| +---+---+ etc... 3|6|9| +---+---+---+ 2|3|5|8| +---+---+---+---+ 1|1|2|4|7| +---+---+---+---+--> x 1 2 3 4 | | | | | | | | | | > (show-stream (slice ((1 1)) > (show-stream (slice ((2 1) (1 2)) > (show-stream (slice ((3 1) (2 2) (1 3)) > (show-stream (slice ((4 1) (3 2) (2 3) (1 etc... 1)) 2)) 3)) 4)) 4)) (a) Write slice. You may create any helper functions you might need, or reference any functions already deﬁned in the reader or SICP. (define (slice n) (b) For this part, assume you have a working version of slice from part (a). Below is an attempt at a solution to diagonal-pairs. (stream-append can be found in SICP p. 340.) (define diagonal-pairs (diagonal-pairs-generator 1)) (define (diagonal-pairs-generator n) (stream-append ( (diagonal-pairs-generator ) ))) EITHER Fill in the blanks above to complete the deﬁnition of diagonal-pairs OR explain below in one sentence why that is impossible. It is impossible because 9 . Question L4 (12 points) – The FBI traced the call all the way to foo! Implement trace and untrace in the metacircular evaluator. This feature should work for both primitive and compound procedures. For simplicity, trace and untrace take exactly one procedure name, and you shouldn’t print spaces at the beginning of trace output to show procedure call depth. You don’t have to do any error-checking for trace or untrace (i.e., we will only call trace and untrace at the top level prompt, trace will always be given a deﬁned untraced procedure, untrace will always be given a deﬁned traced procedure, etc.) For example: > (define (foo a b) (+ (* 3 a) b)) > (foo 2 (+ 4 6)) 16 > (trace foo) ;; We don’t care about the return value > (foo 2 (+ 4 6)) (foo 2 10) starts (foo 2 10) --> 16 16 > (trace +) > (foo 2 (+ 4 6)) (+ 4 6) starts (+ 4 6) --> 10 (foo 2 10) starts (+ 6 10) starts (+ 6 10) --> 16 (foo 2 10) --> 16 > (untrace foo) > (foo 2 (+ 4 6)) (+ 4 6) starts (+ 4 6) --> 10 (+ 6 10) starts (+ 6 10) --> 16 > (untrace +) > (foo 2 (+ 4 6)) ;; back to normal 16 Your job is to modify the metacircular evaluator to make this work. We have provided several possibly relevant procedures from the evaluator on the following pages. (You won’t have to modify all of them!) Make the necessary modiﬁcations; write any required new procedures on this page. Please list below the names of the procedures you modify, to be sure that we don’t overlook one. HAVE A GREAT SUMMER! 10 Your name Question L4 – (continued) mc-eval (define (mc-eval exp env) (cond ((self-evaluating? exp) exp) ((variable? exp) (lookup-variable-value exp env)) ((quoted? exp) (text-of-quotation exp)) ((assignment? exp) (eval-assignment exp env)) ((definition? exp) (eval-definition exp env)) ((if? exp) (eval-if exp env)) ((lambda? exp) (make-procedure (lambda-parameters exp) (lambda-body exp) env)) ((begin? exp) (eval-sequence (begin-actions exp) env)) ((cond? exp) (mc-eval (cond->if exp) env)) ((application? exp) (mc-apply (mc-eval (operator exp) env) (list-of-values (operands exp) env))) (else (error "Unknown expression type -- EVAL" exp)))) mc-apply (define (mc-apply procedure arguments) (cond ((primitive-procedure? procedure) (apply-primitive-procedure procedure arguments)) ((compound-procedure? procedure) (eval-sequence (procedure-body procedure) (extend-environment (procedure-parameters procedure) arguments (procedure-environment procedure)))) (else (error "Unknown procedure type -- APPLY" procedure)))) apply-primitive-procedure (define (apply-primitive-procedure proc args) (apply-in-underlying-scheme (primitive-implementation proc) args)) list-of-values (define (list-of-values exps env) (if (no-operands? exps) ’() (cons (mc-eval (first-operand exps) env) (list-of-values (rest-operands exps) env)))) make-procedure (define (make-procedure parameters body env) (list ’procedure parameters body env)) procedure-parameters (define (procedure-parameters p) (cadr p)) procedure-body (define (procedure-body p) (caddr p)) procedure-environment (define (procedure-environment p) (cadddr p)) login cs61a- 11 Question L4 – (continued) compound-procedure? (define (compound-procedure? p) (tagged-list? p ’procedure)) make-frame (define (make-frame variables values) (cons variables values)) frame-variables (define (frame-variables frame) (car frame)) frame-values (define (frame-values frame) (cdr frame)) extend-environment (define (extend-environment vars vals base-env) (if (= (length vars) (length vals)) (cons (make-frame vars vals) base-env) (if (< (length vars) (length vals)) (error "Too many arguments supplied" vars vals) (error "Too few arguments supplied" vars vals)))) set-variable-value! (define (set-variable-value! var val env) (define (env-loop env) (define (scan vars vals) (cond ((null? vars) (env-loop (enclosing-environment env))) ((eq? var (car vars)) (set-car! vals val)) (else (scan (cdr vars) (cdr vals))))) (if (eq? env the-empty-environment) (error "Unbound variable -- SET!" var) (let ((frame (first-frame env))) (scan (frame-variables frame) (frame-values frame))))) (env-loop env)) primitive-procedure? (define (primitive-procedure? proc) (tagged-list? proc ’primitive)) primitive-implementation (define (primitive-implementation proc) (cadr proc)) (define primitive-procedures (list (list ’car car) (list ’cdr cdr) (list ’cons cons) ;; more primitives )) primitive-procedure-names (define (primitive-procedure-names) (map car primitive-procedures)) primitive-procedure-objects (define (primitive-procedure-objects) (map (lambda (proc) (list ’primitive (cadr proc))) primitive-procedures)) 12 ...
View Full Document
- Summer '01
- Return statement, Error Error Error, incorrect incorrect incorrect, lookup-variable-value exp env, mc-eval exp env, evaluator VALUE ERROR