CS61A Lecture 12 2011-0-11 Colleen Lewis (calc) review (scheme-1) has lambda but NOT define Remember calc-apply? STk> (calc-apply '+ '(1 2 )) 6 STk> (calc-apply '* '(2 4 )) 24 STk> (calc-apply '/ '(10 2)) STk> (calc-apply '- '( 2 1)) (calc) read-eval-print loop (define (calc) (display "calc: ") (flush) (print (calc-eval (read))) (calc)) STk> (calc) calc-eval calc: (+ (* 2 ) 1 (define (calc-eval exp) ((number? exp) exp) ((list? exp) (calc-apply (car exp) (map calc-eval (cdr exp)))) (else (error Calc: bad exp )))) 2 * + 4 (scheme-1) DOES NOT HAVE DEFINE! STk> (scheme-1) Scheme-1: Scheme-1: ( ) 1
Working with large programs! Start with small functions Understanding code Read it Recursively figure out any functions it calls Try to call the function to see what it does in different cases Trace the function and try to call it from the functions that call it. Approximate hierarchy of calls scheme-1 apply-1 substitute lookup maybe-quote lambda-exp? if-exp? quote-exp? exp-checker constant? number? boolean? string? proceedure? lambda-exp? STk> (lambda-exp? ' (+ x 2))) #t STk> (lambda-exp? '(+ ) STk> (lambda-exp? '+) STk> (lambda-exp? '(lambda)) #t It isn t as picky as we might hope Write lambda-exp? in terms of exp-checker (define (exp-checker type) (lambda (exp) (and (pair? exp) (eq? (car exp) type)))) (lambda-exp? ' (+ x 2))) Did you write it with syntactic sugar? A) Yes B)No Some Helpers (define quote-exp? (exp-checker 'quote)) (define if-exp? (exp-checker 'if)) (define (constant? exp) (or (number? exp) (boolean? exp) (string? exp) (procedure? exp))) What is string? STk> (string? "hello") #t STk> (string? 12) STk> (string? 'hello) 2
(lookup name params args) STk> (lookup 'x STk> (lookup 'y '(x y) '(2 )) STk> (lookup 'y y STk> (lookup '* * Just returns it if it isn t in there lookup full functionality STk> (lookup 'fn This already works '(x fn) '( (lambda (y) (* y y)))) (lambda (y) (* y y)) STk> (lookup 'x '(cat)) (quote cat) cat was already a word, but we want to tell other people this thing IS ACTUALLY a word Full lookup (define (lookup name params args) ((null? params) name) ((eq? name (car params)) (maybe-quote (car args)) (else (lookup name (cdr params) (cdr args))))) maybe-quote (define (maybe-quote value) ((lambda-exp? value) value) ((constant? value) value) ((procedure? value) value) (else (list 'quote value)))) Substitution using substitute STk> ( ) '(* x x) '() (* ) STk> ((lambda (x y) (+ x y)) STk>(substitute '(+ x y) '(x y) '( (+ (lambda (y) (* x y)) ) ) What does this return? '() (lambda (y) (* y)) '(lambda (y) (* x y))
Scheme substitution review (* x x)) ) #[closure arglist=(x) ff1a1f8] STk> (( (* x x))) ) What does this return? A) B) 16 C)?? (* x x)) ) #[closure arglist=(x) ff1a1f8] ' '( (apply-1 proc args) STk> (apply-1 + '( ) STk> (apply-1 Unlike calc-apply apply-1 can be called with REAL scheme functions ' Or lists representing functions Remember lambda-exp?? apply-1 (define (apply-1 proc args) ((procedure? proc) (apply proc args)) ((lambda-exp? proc) ( (substitute (caddr proc) (cadr proc) args )) (else (error "bad proc:" proc)))) scheme-1 (define (scheme-1) (display "Scheme-1: ") (flush) (print ( (read))) (scheme-1)) STk> ( ) ((constant? exp) exp) STk> ( '+) #[closure arglist=args ffde8] ((symbol? exp) (eval exp)) 4
STk> ( '(if (> )) ((if-exp? exp) (if ( (cadr exp)) ( (caddr exp)) ( (cadddr exp)))) STk> ( 'x) *** Error: unbound variable: x Current eval stack: 0 x 1 (eval exp) Things like + are quoted: '+ when they are passed to so this assumes x will be a variable not a word. with words STk> ( '(quote x)) x STk> ( ') STk> ( (quote (quote x))) x STk> ( ''x) x ((quote-exp? exp)(cadr exp)) These are all equivalent! ((lambda-exp? exp) exp) (define ( exp) ((constant? exp) exp) ((symbol? exp) (eval exp)) ((quote-exp? exp) (cadr exp)) ((if-exp? exp) (if ( (cadr exp)) ( (caddr exp)) ( (cadddr exp)))) ((lambda-exp? exp) exp) ((pair? exp) (else (error "?!?" exp)))) ((pair? exp) ) STk> ( '(+ 2 )) STk> ( '(+ (- 1) )) STk> ( '( ))
((pair? exp) ) ((pair? exp) (apply-1 ( (car exp)) (map (cdr exp)))) STk> ( '(+ 2 )) STk> ( '(+ (- 1) )) STk> ( '( )) lambda-exp? Solution (define (exp-checker type) (lambda (exp) (and (pair? exp) (eq? (car exp) type)))) (define (lambda-exp? exp) ((exp-checker 'lambda) exp)) (define lambda-exp? (exp-checker 'lambda)) Write lookup (some functionality missing) (define (lookup name params args) ((null? params) name) ((eq? name (car params)) (car args)) (else (lookup name (cdr params) (cdr args))))) Substitution using substitute STk> ( ) '(* x x) '() (* ) STk> ((lambda (x y) (+ x y)) STk>(substitute '(+ x y) '(x y) '( (+ (lambda (y) (* x y)) ) ) What does this return? #[closure arglist=(y) ff1cc48] A procedure that takes argument y and adds to it '(lambda (y) (* x y)) '() (lambda (y) (* y)) (* x x)) ) #[closure arglist=(x) ff1a1f8] A recursive call will be made where bound will be ' '( 6