CS 152 - Lecture 15

Cover page image

Cay S. Horstmann

Review

Apply and Eval

Defining eval/apply in Scheme

Responsibilities of eval and apply

eval

(define (eval exp env) ; env contains bindings of names to values
  (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) (eval (cond->if exp) env))
        ((application? exp)
         (apply (eval (operator exp) env)
                (list-of-values (operands exp) env)))
        (else
         (error "Unknown expression type -- EVAL" exp))))

apply

(define (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))))

Limits of Computation

Macros

A Swap Macro

(define-syntax swap!
    (syntax-rules () ; No keywords—we'll see those later
        (
          (swap! a b) ; Match this pattern
          (let ((c a)) ; Replace with this code
            (set! a b)
            (set! b c))
        )
        ; Other (pattern, code) pairs can come here, e.g. (swap! a b c)
))

Keywords and Varargs

(define-syntax while
    (syntax-rules (do) ; do is a keyword
      ((while condition do body ...) ; body is a sequence of terms
       (letrec ([loop (lambda ()
                        (if condition
                            (let ()
                              body ...
                              (loop))
                            #f))]) (loop)))))

Recursive Definitions

 (define-syntax reverse 
    (syntax-rules ()
      ; First case terminates recursion 
      ((reverse e) (list e)) ; or (cons e nil)—(e) would try to evaluate e
      ; Second case invokes macro recursively
      ((reverse e es ...) (append (reverse es ...) (list e)))))

Macros in Other Languages

Lab

???

Step 1 - An Enhanced for Loop

In this step, we want to make a macro for a Java-style loop over the elements of a list, like this:

(for i in '(1 2 3 4 5) do (print i) (newline))
  1. What Scheme code should the macro generate? (Hint: map)

    Write down the exact code you want to generate for this example.

  2. The variable i in the for statement was not declared previously, and that's how we like it. Where does it get defined? (Hint: Look at the lambda that the map gets.)
  3. What are the keywords of your macro?
  4. What pattern do you match?
  5. What is your macro?
  6. Exactly what gets printed when you run the for statement above? Is there something you can/should do to improve that?
  7. How can you make the do optional?
  8. Your for macro can loop over any list. Make a different macro repeat that repeats the given actions a given number of times, such as
    (repeat 10 (print "Hello") (newline))
    

Step 2 - Code Generation

In this step, we will write Scheme code that reads and writes Scheme expressions such as the following:

(define poly '(lambda (x) (+ (* x x) (* x 2) 10))) ; Note the quote
  1. What is the type of the value to which poly is set?
  2. How do you compute the value of this polynomial when x is -1?
  3. Now we want to compute derivatives of such polynomials. We'll assume that each * has only two arguments, and that the expression contains only + and * as operators.

    Write a helper function (deriv expr var) that computes the derivative with respect to the given variable. For example,

    (deriv '(+ (* t t) (* t 2)) 't) 
      ; yields '(+ (+ (* 1 t) (* t 1)) (+ (* 1 2) (* t 0)))  ; maybe in a different order

    What is the code of your helper function?

  4. Now write a function derivative, so that
    (derivative poly)

    is a list of the form (lambda (var) ...)

    What is the code of your function?

  5. Now give the values of the derivative for x = -20 ... 20 (Hint: range from the slides and map)

    What expression do you use?