;; The first three lines of this file were inserted by DrScheme. They record metadata ;; about the language level of this file in a form that our tools can easily process. #reader(lib "htdp-intermediate-lambda-reader.ss" "lang")((modname untitled-lect07a) (read-case-sensitive #t) (teachpacks ((lib "universe.ss" "teachpack" "2htdp"))) (htdp-settings #(#t constructor repeating-decimal #f #t none #f ((lib "universe.ss" "teachpack" "2htdp"))))) (require scheme/contract) ; Load the library. ; all Loops ; are equivalent to a tail-recursive functions ; (Note: not all recursive functions are equivalents to loops) ; Many loops are doing one of three things: ; map -- e.g. move-trucks ; filter ; fold ; (for-each -- like map, but hit each item with an imperative ; function, and don't return a (list of) values. ; for side effect only. ; e.g. ; (for-each display (list "a" "b" 3 'four)) ; (Must be in advanced-student to allow side-effects like `display` or `set!`.) ; (map move-truck lot) #;(define (update-world a-w) (make-world (map move-truck (world-trucks a-w)) ... ...)) ; In scheme: ; Functions are values (just like numbers, strings, images, ...) ; "functions are first-class objects" ; You can pass them as inputs. ; How can we generalize the following pattern? ; ;(define (move-trucks alot) ; (cond [(empty? alot) empty] ; [(cons? alot) ; (cons (move-truck (first alot)) ; (move-trucks (rest alot)))])) ; ;(define (sqeach alon) ; (cond [(empty? alon) empty] ; [(cons? alon) ; (cons (sqr (first alon)) ; (sqeach (rest alon)))])) ;(map move-truck (list tr1 tr2 tr3)) (map sqr (list 3 4 5)) ; map : (α -> β), (listof α) -> (listof β) ; (define (my-map fn lst) (cond [(empty? lst) empty] [(cons? lst) (cons (fn (first lst)) (my-map fn (rest lst)))])) (check-expect (my-map even? (cons 3 (cons 4 (cons 5 empty)))) (cons false (cons true (cons false empty)))) ;;;;;;; Wed: ;;;;;;;;;; ; Write `filter` ; (filter even? (list 3 4 5 6 7 9 8)) (list 4 6 8) ; filter : (α -> boolean) (listof α) -> (listof α) ; (define (my-filter keep? data) (cond [(empty? data) empty] [(cons? data) (if (keep? (first data)) (cons (first data) (filter keep? (rest data))) (my-filter keep? (rest data)))])) #;(filter truck-on-screen? (map move-truck (world-trucks a-world))) ; filter>= : (-> number? (listof number?) (listof number?)) ; Remove all items from nums which aren't >= thresh. ; (define (filter>= thresh nums) (filter (λ (n) (>= n thresh)) nums)) (check-expect (filter>= 5 empty) empty) (check-expect (filter>= 5 (list 7)) (list 7)) (check-expect (filter>= 5 (list 3)) empty) (check-expect (filter>= 5 (list 3 7 2 0 9 5)) (list 7 9 5)) ; prefix*: (string? (listof string?) . -> . (listof string?)) ; Return a list where every element of `wrds` is appended to `pref`. ; (define (prefix* pref wrds) (map (lambda (wrd) (string-append pref wrd)) wrds) ) (check-expect (prefix* "Dr. " empty) empty) (check-expect (prefix* "Dr. " (list "Who")) (list "Dr. Who")) (check-expect (prefix* "Dr. " (list "Dre" "Doom" "Who")) (list "Dr. Dre" "Dr. Doom" "Dr. Who")) (check-expect (prefix* "Howdy " (list "pardner" "friend" "frenemy")) (list "Howdy pardner" "Howdy friend" "Howdy frenemy")) ; Note that a function is separate from *naming* the function: ;(define (f x) (+ x 3)) ;(define f (lambda (x) (+ x 3))) ; ;(f 17) ((lambda (x) (+ x 3)) 17) ;;; google API "map/reduce" ; What is in common about all functions handling the template? ; foldr (define (my-foldr how-to-combine base-case data) (cond [(empty? data) base-case] [(cons? data) (how-to-combine (first data) (my-foldr how-to-combine base-case (rest data)))])) (define (my-foldl how-to-combine so-far data) (cond [(empty? data) so-far] [(cons? data) (my-foldl how-to-combine (how-to-combine (first data) so-far) (rest data))])) (foldr + 0 (list 3 4 5)) (my-foldr string-append "" (list "aye " "bee " "sea ")) (my-foldl string-append "" (list "aye " "bee " "sea ")) (foldr string-append "" (list "aye " "bee " "sea ")) (foldl string-append "" (list "aye " "bee " "sea ")) ;;;;; ; What about all accumulator functions? ; foldl ; ;; Challenge: implement 'my-map' in terms of 'my-fold'. ;; 'fold' is also called 'reduce'; ;; compare to the google cloud's API "map/reduce" -- ;; like map and fold (but they also tag each mapped result ;; with the number of times that input value was seen). ;; ;; Note: ;; Functional programming plays well w/ parallel processing. ;; We can take any sub-expression and send it to any processor; ;; there are no mutations to worry about what order things happen in. ;; E.g. (make-world (f1 w) (f2 w) (f3 w)) ;; (f (first nums)) ... (g (rest nums)) ;; map, filter ;; ;; (Though still, `(f (g x))` has to have `g` finish before `f` starts.)