What we've studied so far

Foundations:
* Grammars as set definitions
 membership proofs
 concrete and abstrct syntax via grammars
* Evaluation through reduction steps
* A small dialect of Scheme (as an archetypal functional language)
 define, cond, let, let*, letrec, lambda, function call,
definedatatype, cases, begin,
numbers, booleans, symbols, pairs (and lists), vectors
* Processing members of sets
 especially members of recursivelydefined sets
 contracts, examples, templates
 interpreter as a prominent example
Language constructs:
* Lexical scope
 free, binding, and bound occurrences
 environments
 let, letrec, let*
(let ([x 7]
[y x]) : << free x
...) ; << let bindings start here
(let* ([x 7]
[y x]) ; << bound x, x binding starts here
...) ; << y binding start here
;; v x, y binding start here
(letrec ([x (lambda (z) y)] ;; bound y
[y (lambda (z) x)]) ;; bound x
...)
* Functions and closures
 firstorder (at toplevel) versus higherorder
(at expressions)
 evaluation of `proc' and function calls
Exam Content

Inclass, openbook, opennotes.
The exam might...
... show you a brandnew datatype, and ask you to generate
examples, and perhaps prove that an example is valid.
E.g.:
= 'wabe
 (cons 'gyre )
 (list 'gimble )
Or, equivalently:
A slithytove is one of
* 'wabe
* (cons 'gyre st)
* (cons st 'gimble st)
where st is a slithytove
'wabe (list 'wabe 'gimble 'wabe)
Which of the following expressions produce slithytoves?
* 1  no
* 'wabe  yes
* (cons 'gyre (list 'wabe 'gimble 'wabe))  yes
Prove that (cons 'gyre (list 'wabe 'gimble 'wabe)) is a
slitytove:
'wabe in 'wabe in

(list 'wabe 'gimble 'wabe) in

(cons 'gyre (list 'wabe 'gimble 'wabe)) in
Another example, this time with more than one datatype:
= 1
 (list )
= 0

Which of the following expressions produce pings?
1  yes
2  no
(list 0 0)  yes
(list 1 (list 0 0)) yes
Prove that the last example above is a ping:
0 in 0 in

1 in (list 0 0) in
 
1 in (list 0 0) in

(list 1 (list 0 0)) in
... ask you to write functions for a given datatype.
!!! Your answer MUST implement the function in a way that !!!
!!! follows the data definition. !!!
You may be asked to write examples, too.
For example, suppose you are asked to implement
"slithytovegyres?" which takes a slitytove and returns #t
if it contains 'gyre, #f otherwise.
a. The contract is:
slithytovegyres? : slithytove > bool
b. Examples:
(slithytovegyres? 'wabe) = #f
(slithytovegyres? (cons 'gyre 'wabe)) = #t
(slithytovegyres? (list 'wabe 'gimble 'wabe)) = #f
Note that every case of the data definition is covered by an
example!
The following is a BAD EXAMPLE and would be rejected:
(slithytovegyres? 'gyre) = #t
because 'gyre is not a slithytove.
c. The implementation must have the following template shape:
(define (slithytovegyres st)
(cond
[(eq? st 'wabe) ...]
[(eq? (car st) 'gyre) ... (slithytovegyres (cdr st))...]
[else ... (slithytovegyres (car st)) ...
(slithytovegyres (caddr st)) ...]))
Of course, your answer may choose a different name for the
function argument; the test to find the "wabe" case could use
"symbol?"; and "else" could be replaced with a specific test.
But there is NO CHOICE in the overall form of the "cond", or
the placement of recursive calls.
(define (slithytovegyres? st)
(cond
[(eq? st 'wabe) #f]
[(eq? (car st) 'gyre) #t]
[else (or (slithytovegyres? (car st))
(slithytovegyres? (caddr st)))]))
Example #2: Implement `pingsum', which takes a ping and adds up
its numbers.
; pingsum : ping > num
; (pingsum 1) = 1
; (pingsum (list 1 (list 1 1))) = 3
(define (pingsum p)
(cond
[(and (number? p) (= p 1)) 1]
[else (+ (pongsum (car p)) (pongsum (cadr p)))]))
; pongsum : pong > num
; (pongsum 0) = 0
; (pongsum 1) = 1
(define (pongsum p)
(cond
[(and (number? p) (= p 0)) 0]
[else (pingsum p)]))
An example *unacceptable* answer:
(define (pingsum p)
[(number? p) p]
[else (+ (pingsum (car p)) (pingsum (cadr p)))])
... ask you to understand a program using "definedatatype" and
"cases". For example, given:
(definedatatype
slithytove slithytove?
(wabetove ())
(gyretove (st slithytove?))
(gimbletove (st slithytove?)
(another slithytove?)))
(define (f st)
(cases slithytove st
(wabetove () 0)
(gyretove (innerst) (+ 1 (f innerst)))
(gimbletove (innerst anotherst) (+ (f innerst)
(f anotherst)))))
You should be able to predict the value of
(f (gyretove
(gyretove
(gyretove (gimbletove (wabetove)
(wabetove))))))
... ask you about lexical scope. You might have to draw arrows to
show bindings, or compute lexical addresses.
Given an expression
let x = 3
y = w
in let x = 7
y = x
in letrec f = proc(z)(f +(z,x))
in (f y)
* Draw arrows from bound variable to binding occurrences:
v.
let x = 3 \
y = w \
in let x = 7 </.
,> y = x ' v. \
/ in letrec f = proc(z)(f +(z, x))
\ ,^'
`.
in (f y)
* List the free vars: w
* List the bound vars: x y z f
... ask about environments and closures at points in an
evaluation.
Given the following expression for a callbyvalue language
(denoted values = expressed values):
let y = 2
in let f = proc(x)+(x,y)
in (f 3)
* Describe the closure bound to "f" at the
point where "(f 3)" is the current expression.
Args: x
Body: +(x,y)
Environment: { y = 2 }
* Describe the environment at the point during evaluation where
"+(x,y)" is the current expression.
Environment: { y = 2, x = 3}
Given the following expression (denoted values = expression
values):
let g = let a = 10
in proc(z)a
in let f = proc(w)(g w)
in (f 1)
* Describe the closure bound to "g" at the
point where "(g w)" is the current expression.
Args: z
Body: a
Environment: { a = 10 }
* Describe the environment at the point during evaluation where
"(f 1)" is the current expression.
Environment: { f = }>,
g = }
... ask you to "play interpreter", showing the recursive calls to
an evaluation expression.
Given the following expression:
let y = 2
in let f = proc(x)+(x,y)
in (f 3)
Describe a trace of the evalaution in terms of arguments to an
"evalexpression" interpreter function for every call. For
literal, variable, and proc expressions, show the result.
eval expr = let y = 2 in let f = proc(x)+(x,y) in (f 3)
env = { }
eval expr = 2
env = { }
result = 2
eval expr = let f = proc(x)+(x,y) in (f 3)
env = E1 = { y = 2 }
eval expr = proc(x)+(x,y)
env = E1
result =
eval expr = (f 3)
env = E2 = { f = , E1 }
eval expr = f
env = E2
result =
eval expr = 3
env = E2
result = 3
eval expr = +(x, y)
env = { x = 3 , E1 }
eval expr = x
env = {x = 3 , E1}
result = 3
eval expr = y
env = {x = 3 , E1}
result = 2
A more subtle example for practice:
let g = let a = 10
in proc(z)a
in let f = proc(w)(g w)
in (f 1)