Computer Science 61A: Structure and Interpretation

advertisement
Computer Science 61A Study Group
Student Learning Center
Leader: Joo-Rak Son
Week 7, October 11th (Monday)
Computer Science 61A: Structure and Interpretation
of Computer Programs - Study Group
Student Learning Center, University of California at Berkeley
[Week 7, October 13th (Monday)]
Topic of Today
– Data-directed Programming
Announcements
– Sessions: Monday 6-7:30PM, Wednesday 7-8:30PM, 83 Dwinelle.
– SLC Drop-in Tutoring: Monday 10-4, Tuesday 10-2, Wednesday 10-4, Thursday 9-3, Friday 9-12.
– Please send suggestions, comments, or request for emphasis on certain topics to joorak@berkeley.edu.
1. Practices with DDP
Below is the self-evalution code given in the lecture. The following are their implementations and
interfaces (specifications of parameters and return values). Note you don't have to have gone to the
lecture in order to solve this problem (so relax). You don't need to understand the entire implementation,
but just try to get an idea of how to use the procedures.
;; eval: takes an expression (note this is different from Scheme
;;
expression) and environment bindings as its argument and
;;
returns the result of evalution of the given expression.
(define (eval exp env)
((cadr (assoc (operator exp) eval-table))
;; Above extracts the lambda procedure that corresponds to the
;; operator of the given expression, and the operands will be
;; applied to it.
(extra-data exp)
(map (lambda (opnd) (eval opnd env)) (operands exp))
;; Two arguments to this extracted procedure are the 'extra-data'
;; and the 'operands (ops)'.
env))
;; The last argument is the given environment.
;; make-expr: takes the operator, extra-data, and operands (optional
;;
or as many as you want) as its arguments and returns
;;
the resulting expression. Note that the operator is
;;
rather used like a type-tag.
(define (make-expr operator extra-data . operands)
(list operator extra-data operands))
;; Some
(define
(define
(define
selectors of the 'self-evaluation expression' data structure.
operator car)
operands caddr)
extra-data cadr)(a) Using several calls to make-expr, make a self-evaluating expression
that corresponds to Scheme's (+ 4 19).
> (make-expr '+ '() (make-expr 'const 4) (make-expr 'const 19))
(+ () ((const 4 ()) (const 19 ())))
1
Computer Science 61A Study Group
Student Learning Center
Leader: Joo-Rak Son
Week 7, October 11th (Monday)
(b) As you might've noticed already, eval utilizes eval-table, where all lambda procedures for
every expression type are found. You are given a table that handles types +, const (a constant
number), and var (a variable) below. Extend this table so that it will also handle the primitive
procedures cons and cadr.
(define eval-table
(list (list '+ (lambda (extra ops env) (apply + ops)))
(list 'const (lambda (const ops env) const))
(list 'var (lambda (var ops env) (cadr (assoc var env))))
(list 'cons (lambda (extra ops env)
(cons (car ops) (cadr ops))))
(list 'cadr (lambda (extra ops env)
(cadr (car ops))))))
2. Implementing Lambda
From problem 1, you probably noticed that the usage of environment is pretty lame. That's right. The
user has to manually make his own environment and shove it into eval, and it stays the same throughout
the entire evaluation.
Let's define enhance our eval so that it can recognize lambda expressions and be able to extend the
environment. A lambda expression will look like this:
STk> (make-expr 'lambda '((parameters) (body))
(make-expr 'const 5) (make-expr 'const 7))
(lambda ((parameters) (body)) ((const 5 ()) (const 7 ())))
A lambda expression, like above, has the string “lambda” as its operator (or type-tag), and its extravariable is a list whose car is the list of parameters and whose cadr is the body of the expression. And
of course, the rest of the expression is optional operand/operands like other expressions.
Your job is to add to the eval-table from problem 1(a) so that it will include the procedure that
handles lambda expressions.
(define eval-table
(list (list '+ (lambda (extra ops env) (apply + ops)))
(list 'const (lambda (const ops env) const))
(list 'var (lambda (var ops env) (cadr (assoc var env))))
;; Your code goes here.
(list 'lambda (lambda (extra ops env)
(eval (cadr extra)
(append (construct-env (car extra) ops))
env))))))
;; Assuming L1 and L2 are of same length.
(define (construct-env L1 L2)
(if (null? L1) '()
(cons (list (car L1) (car L2))
(construct-env (cdr L1) (cdr L2)))))
2
Computer Science 61A Study Group
Student Learning Center
Leader: Joo-Rak Son
Week 7, October 11th (Monday)
3. Implementing Cutie Printer
Now, we will be dealing with a two dimensional table in our DDP. In order to do this, each expression,
instead of having the operator identifier in front, has a reference to the column of a table that
corresponds to that particular operator. Below is an example of a two-dimensional table, the compute
procedure that operates on it, and an example of an expression in this case.
(define table-for-+
(list (list 'eval (lambda
(list 'count-consts
(define table-for-var
(list (list 'eval (lambda
(list 'count-consts
(define table-for-const
(list (list 'eval (lambda
(list 'count-consts
(extra ops env) ...))
(lambda (extra ops env)...))))
(var ops env)...))
(lambda (extra ops env) 0))))
(const ops env)...))
(lambda (extra ops env) 1))))
;; Given an expression and environment, perform the operation
;; specified in the expression.
(define (compute operation exp env)
((cadr (assoc operation (operator exp)))
(extra-data exp)
(map (lambda (opnd) (compute operation opnd env)) (operands exp))
env))
STk> (make-expr table-for-+ '()
(make-expr table-for-const 'const 6)
(make-expr table-for-const 'const 2))
(#[proc-1] () ((#[proc-2] 6 ()) (#[proc-2] 2 ())))
(a) Add one more binding to each of the tables above—table-for-+, table-for-var, and
table-for-const. Type-tag this new operation as 'qtprinter (as opposed to 'eval and
'count-consts) and implement its lambda procedures will produce a nice little Scheme style list
representation of the input expression when run under compute. Here is an example of using this cutie
printer.
STk> (define x (make-expr table-for-+ '()
(make-expr table-for-const 'const 6)
(make-expr table-for-const 'const 2))
x
STk> (compute 'qtprinter x '()
(+ 6 2)
Problem continues on the next page.
3
Computer Science 61A Study Group
Student Learning Center
Leader: Joo-Rak Son
Week 7, October 11th (Monday)
(define table-for-+
(list (list 'eval (lambda (extra ops env) ...))
(list 'count-consts (lambda (extra ops env)...))))
;; Your code for ‘qtprinter goes here.
(list 'qtprinter (lambda (extra ops env)
(cons '+ ops)))))
(define table-for-var
(list (list 'eval (lambda (var ops env)...))
(list 'count-consts (lambda (extra ops env) 0))))
;; Your code for ‘qtprinter goes here.
(list 'qtprinter (lambda (var ops env) (list var)))))
(define table-for-const
(list (list 'eval (lambda (const ops env)...))
(list 'count-consts (lambda (extra ops env) 1))))
;; Your code for ‘qtprinter goes here.
(list 'qtprinter (lambda (const ops env) (list const)))))
(b) Further add cutie printer-infix operation to each of the tables. Type tag these operations as 'qtprinterinfix. This should be essentially the same as part (a), except that the operators should between the
operands. This is called the infix notation. Do this in the room given for part (a).
STk> (define x (make-expr table-for-+ '()
(make-expr table-for-const 'const 1)
(make-expr table-for-const 'const 3)
(make-expr table-for-const 'const 5)
x
STk> (compute 'qtprinter-infix x '()
(6 + 2 + 5)
The answer for b is the same as a except that for +, you need to have + symbols between every pair of
operands. In order to solve this, you will need a helper-function, stick-in-plus-symbols, which will add
the operator symbol inbetween every operands.
4
Download