CS 227 Lecture -*- Outline -*- * Unrestricted lambda (7.2, pages 197 -- 201) A diversion... a bit more power to write things like writeln, error Scheme allows us to define procedures that take any number of arguments --- like writeln, list. ** Problem -- to define a procedure that takes any number of parameters, that procedure thinks it takes a list of arguments, and Scheme automatically forms a list out of its arguments when it is called. -- Why? because a list can have any number of elements. ---------------- A PROBLEM SOLVABLE WITH UNRESTRICTED LAMBDA (sum-sqrs 1 3 5 7) ==> 84 (sum-sqrs 2 4) ==> 20 (sum-sqrs) ==> 0 add: (-> (number ...) number) ---------------- -- the unrestricted lambda syntax just tells Scheme to do that. ** Syntax --------------- UNRESTRICTED LAMBDA Syntax: (LAMBDA var ;; no parentheses body) --------------- no parentheses around var the meaning is that the var is bound to the arguments, in a list. -------------- Meaning: ((lambda args E) x y z ...) = ((lambda (args) E) (list x y z ...)) = (let ((args (list x y z ...))) E) Example: ((lambda args (car args)) 1 2) = ((lambda (args) (car args)) (list 1 2)) = (car (list 1 2)) ==> 1 ------------- like other lambdas, body has an implicit begin. ** Examples *** sum-sqrs write this. Idea is to make a helping proc list-sum-squares such that (sum-sqrs x y z ...) = (list-sum-sqrs (list x y z ...)) (define sum-sqrs ; TYPE: (-> (number ...) number) (letrec ((square (lambda (x) (* x x))) (list-add-sqrs ; TYPE: (-> ((list number)) number) (lambda (ls) (if (null? ls) 0 (+ (square (car ls)) (list-add-sqrs (cdr ls))))))) (lambda args (list-add-sqrs args)))) *** writeln and for-each Writeln is also done this way ---------------- WRITELN AND FOREACH ; - Program 7.5, pg. 199 - (define writeln ; TYPE: (-> (datum ...) void) (lambda args (for-each display args) (newline))) ; - Program 7.2, pg. 197 - (define for-each ; TYPE: (-> ((-> (datum) void) ; (list datum)) ; void) (lambda (proc ls) ; EFFECT: apply proc to items of ls ; in order, starting with car of ls (if (not (null? ls)) (begin (proc (car ls)) (for-each proc (cdr ls)))))) ---------------- What is the type of writeln? of for-each? See how they fit together: -- inside the body of writeln, args is a list, and for-each takes a procedure and a list. How to understand writeln? (writeln a b c ...) = (begin (display a) (display b) (display c) ... (newline)) This gives us a clue as to how to understand for-each because (writeln a b c ...) = (begin (for-each display (list a b c ...)) (newline)) so (for-each p (list a b c ...)) = (begin (f a) (f b) (f c) ...) Q: What are the recursive equations for for-each? (for-each p '()) = (if #f 'ignored) (for-each p (cons x l)) = (begin (p x) (for-each p l)) *** make-poly Can use this to make a more convenient interface to digits -> poly. ---------------- (print-poly (make-poly 5.2 3.1 2.8)) =prints=> 5.2 x^2 + 3.1 x + 2.8 (define make-poly ; TYPE: (-> (number ...) poly) (lambda digits (digits->poly digits))) ---------------- *** general equation for unrestricted lambda. ((lambda args (f args)) x y z ...) = (f (list x y z ...)) ** Apply What if you want to go the other way? from a procedure that takes a list to call one that uses unrestricted lambda. Or what if you want to program something like sum-sqrs recursively -- without using a helping proc. Have to "spread out" the arguments from a list. Apply does this. ---------------- APPLY (apply + '(1 2)) ==> 3 (apply * '(1 2 3)) ==> 6 apply: (-> ((-> (datum...) datum) (list datum)) datum) ------------- general equation for apply ------------- (apply f (list x y z ...)) = (f x y z ...) ---------------- ---------------- (define sum-sqrs (let ((square (lambda (x) (* x x)))) ; TYPE: (-> (number ...) number) (lambda nums (if (null? nums) 0 (+ (square (car nums)) (apply sum-sqrs (cdr nums)))) ))) ----------------