;;; Foldr and map! ;;; Fold all the items together using op as the combining operation . ;;; What is the signature for this function? (define (my-foldr op base items) ; The name foldr is already taken... (cond [(empty? items) base] [else (op (first items) (my-foldr op base (rest items)))])) (my-foldr + 0 (list 4 1 2 9)) ; Add up a bunch of numbers (my-foldr * 1 (list 4 1 2 9)) ; Multiply a bunch of numbers ;;; Why the "r" in the name? ;;; Foldr combines the list elements *r*ight-to-left. ;;; (Yes, there is a foldl...) ;;; One way to visualise it: Foldr replaces every cons in the list ;;; with op, and the final empty with base: (cons 4 (cons 1 (cons 2 (cons 9 empty)))) ; This (+ 4 (+ 1 (+ 2 (+ 9 0 )))) ; gets folded to this. ;;; Can operate on strings... (my-foldr string-append "" (list "john" "paul" "george" "ringo")) ;;; Combining function can be more sophisticated. ;;; Plop a bunch of images down onto a base scene. ;;; Go right-to-left: first overlay the big blue circle onto the rectangle, ;;; then overlay the small red circle onto that. (my-foldr overlay (rectangle 100 100 'outline 'green) (list (circle 30 'solid 'red) (circle 50 'solid 'blue))) ;; Problem: can we use fold-r to add dots to an empty scene ;; given a list of their posns? ;; [Listof Posn] Image -> Image (define (add-images-to l scene) (cond [(empty? l) scene] [else (add-dot (first l) (add-images-to (rest l) scene))])) ;; Posn Image -> Image (define (add-dot p scene) (place-image (circle 3 'solid 'red) (posn-x p) (posn-y p) scene)) (add-images-to (list (make-posn 10 10) (make-posn 30 30)) (empty-scene 100 100)) ;;; Now add-images-to is a one-liner! (define (add-images-to.v2 l scene) (fold-r add-dot scene l)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; --- more abstractions --- ;;; Increment every element of l: (define (all+1 l) (cond [(empty? l) empty] [else (cons (add1 (first l)) (all+1 (rest l)))])) ;;; Decrement every element of l: (define (all-1 l) (cond [(empty? l) empty] [else (cons (sub1 (first l)) (all-1 (rest l)))])) (equal? (all+1 (list 1 2 3)) (list 2 3 4)) (equal? (all-1 (list 1 2 3)) (list 0 1 2)) (define (apply-all f l) (cond [(empty? l) empty] [else (cons (f (first l)) (apply-all f (rest l)))])) (apply-all positive? (list -1 4 -3 2)) ;;; Produces (list #f #t #f #t) ;;; Apply-all is already defined! It's actually called "map". ;;; Now, let's do something really out-there... ;;; What's my signature? (define (apply-to-five f) (f 5)) (map apply-to-five (list add1 sub1 sqr)) ;;; Whoa -- functions that apply a function to lists of functions. ;;; New idea: ;;; Once functions are data, ;;; signatures are just data definitions. ;;; A data definition describes a class of data. ;;; The data definition "Bool -> Number" is the class of data ;;; that is all functions that consume a boolean and produce a number. ;;; So the signature for apply-to-five is: ;;; [Number -> Number] -> Number ;;; It is a function that consumes a Number->Number function and ;;; produces a number...