SLIDE 1
Reflection
Consider the member? function, which has the following algebraic laws:
(member? m ’()) == #f (member? m (cons m ks)) == #t (member? m (cons k ks)) == (member? m ks), m != k This algorithm searches for an element in a list. List other algorithms you are familiar with that operate over a list (or linked list, or an array) and explain briefly what they do.
SLIDE 2 Predefined list algorithms
Some classics:
- exists? (Example: Is there a number?)
- all?
(Example: Is everything a number?)
- filter (Example: Select only the numbers)
- map
(Example: Add 1 to every element)
(Visit every element; also called reduce, accum, a “catamorphism”)
SLIDE 3 Defining exists?
; (exists? p? ’()) = #f ; (exists? p? (cons y ys)) = #t, if (p? y) ; (exists? p? (cons y ys)) = (exists? p? ys),
- therwise
- > (define exists? (p? xs)
(if (null? xs) #f (if (p? (car xs)) #t (exists? p? (cdr xs)))))
- > (exists? number? ’(1 2 zoo))
#t
- > (exists? number? ’(apple orange))
#f
SLIDE 4
Coding Interlude: exists?
Define a list ys and two predicates p1? and p2? such that exists? p1? ys evaluates to #t and exists? p2? ys evalutes to #f. Run the code to confirm your answers are correct. An alternative formulation of the algebraic laws for the exists? function is: ;; (exists? p? ’() = #f ;; (exists? p? (cons x xs)) = (|| (p? x) ;; (exists? p? xs)) Modify the definition of exists? following this algebraic formulation instead, and re-run your
SLIDE 5
examples.
SLIDE 6 Defining filter
; (filter p? ’()) == ’() ; (filter p? (cons y ys)) == ; (cons y (filter p? ys)), when (p? y) ; (filter p? (cons y ys)) == ; (filter p? ys), when (not (p? y))
(if (null? xs) ’() (if (p? (car xs)) (cons (car xs) (filter p? (cdr xs))) (filter p? (cdr xs)))))
SLIDE 7 Running filter
n 0)) ’(1 2 -3 -4 5 6)) (1 2 5 6)
- > (filter (lambda (n) (<= n 0)) ’(1 2 -3 -4 5 6))
(-3 -4)
SLIDE 8
Coding Interlude: filter
Use lambda to define a predicate that returns true iff the argument is a number larger than 9. Define a list ys that contans a mix of one- and two-digit numbers. Use your lambda function and the filter function defined in the video to produce a new list zs that contains only the elements in ys with at least two-digits. Run your code. How would you modify the code to produce a list with only one-digit numbers?
SLIDE 9 Your turn: map
Complete the algebraic laws for the map function:
add3 ’(1 2 3 4 5)) (4 5 6 7 8) ;; (map f ’()) = ;; (map f (cons y ys)) =
SLIDE 10 Answers: map
add3 ’(1 2 3 4 5)) (4 5 6 7 8) ; (map f ’()) == ’() ; (map f (cons y ys)) == (cons (f y) (map f ys))
SLIDE 11 Defining and running map
; (map f ’()) == ’() ; (map f (cons y ys)) == (cons (f y) (map f ys))
(if (null? xs) ’() (cons (f (car xs)) (map f (cdr xs)))))
- > (map number? ’(3 a b (5 6)))
(#t #f #f #f)
- > (map (lambda(x)(* x x)) ’(5 6 7))
((25 36 49)
SLIDE 12
Foldr
SLIDE 13 Algebraic laws for foldr
Idea:
+ : :x1 +
+ 0
(foldr (plus zero ’())) = zero (foldr (plus zero (cons y ys))) = (plus y (foldr plus zero ys))
Note: Binary operator + associates to the right. Note: zero might be identity of plus.
SLIDE 14 Code for foldr
Idea:
+ : :x1 +
+ 0
- > (define foldr (plus zero xs)
(if (null? xs) zero (plus (car xs) (foldr plus zero (cdr xs)))))
(lambda (xs) (foldr + 0 xs)))
10
- > (val prod (lambda (xs) (foldr * 1 xs)))
- > (prod ’(1 2 3 4))
24
SLIDE 15
Another view of operator folding
’(1 2 3 4) = (cons 1 (cons 2 (cons 3 (cons 4 ’())))) (foldr + 0 ’(1 2 3 4)) = (+ 1 (+ 2 (+ 3 (+ 4 0 )))) (foldr f z ’(1 2 3 4)) = (f 1 (f 2 (f 3 (f 4 z ))))
SLIDE 16 Check your understanding: foldr
What does the following code evaluate to?
- > (define foldr (plus zero xs)
(if (null? xs) zero (plus (car xs) (foldr plus zero (cdr xs)))))
- > (define combine (x a) (+ 1 a))
- > (foldr combine 0 ’(2 3 4 1))
- 10
- 24
- 4
Answer: 4. The plus function for this invocation of
SLIDE 17 foldr is the function combine, which adds one to an accumulator a for each element x in the list. The zero function for this invocation of foldr is the literal 0. Hence this invocation of foldr starts with 0 and adds 1 for each element in the list, returning 4 when applied to the list '(2 3 4 1) because that list has four elements. This use of foldr is one way
- f writing the list length function.
SLIDE 18 Your turn: Explain the design
- 1. Functions like exists?, map, filter are
subsumed by
- 2. Function foldr, which is subsumed by
- 3. Recursive functions
Seems redundant: Why?
SLIDE 19
Currying: The motivation
Remember me? q-with-y? = (lambda (z) (q? y z)) Happens so often, there is a function for it: q-with-y? = ((curry q?) y) Called a partial application (one now, one later)
SLIDE 20 Map/search/filter love curried functions
((curry +) 3) ’(1 2 3 4 5)) ; add 3 to each element
- > (exists? ((curry =) 3) ’(1 2 3 4 5))
; is there an element equal to 3?
((curry >) 3) ’(1 2 3 4 5)) ; keep elements that 3 is greater then
SLIDE 21 The idea of currying
The function curry
- Input: a binary function f(x,y)
- Output: a function f'
– Input: argument x – Output: a function f'' * Input: argument y * Output: f(x,y) What is the benefit?
- Functions like exists?, all?, map, and filter expect a
function of one argument. To get there, we use currying and partial application. Slogan: Curried functions take their arguments “one-at-a-time.”
SLIDE 22
What’s the algebraic law for curry?
... (curry f) ... = ... f ... Keep in mind: All you can do with a function is apply it! (((curry f) x) y) = (f x y) Three applications: so implementation will have three lambdas
SLIDE 23 From law to code
;; curry : binary function -> value -> function ;; (((curry f) x) y) = (f x y)
(lambda (f) (lambda (x) (lambda (y) (f x y)))))
- > (val positive? ((curry <) 0))
SLIDE 24 Check your understanding: curry
What does the following code evaluate to?
((curry +) 3) ’(1 2 3 4 5))
- 15
- 18
- '(4 5 6 7 8)
- '(1 2 3 3 4 5)
- '(3 4 5 6 7 8)
- 4
Answer: '(4 5 6 7 8). The map function applies its argument function ((curry +) 3) to each element in the list '(1 2 3 4 5), to produce the list '(4 5 6 7 8).
SLIDE 25 The function ((curry +) 3) is the “plus-three” function obtained by partially applying the curried + function to the constant 3. The + function has to be curried before being applied to 3 because it
- therwise takes two arguments at a time, not just
- ne.
An invariant of the map function is that it will always return a list with the same length as its argument.
- > (exists? ((curry =) 3) ’(1 2 3 4 5))
- '()
- #t
- #f
SLIDE 26 Answer: #t. The exists? function applies its argument predicate ((curry =) 3) to each list element until it finds one where the predicate evalutes to true (#t). If it reaches the end of the list without finding such an element, it returns false (#f). The predicate is the “equal-three?” function,
- btained by partially applying the curried equality
function to the constant 3. The equality function has to be curried before being applied to 3 because it otherwise takes two arguments at a time, not just
((curry >) 3) ’(1 2 3 4 5))
SLIDE 27 ; tricky
- '(1 2)
- '(1 2 3)
- ’()
- '(3 4 5)
- '(4 5)
Answer: '(1 2). The filter function applies its argument predicate ((curry >) 3) to each list element, including in the resulting list only those that evaluate to true (#t). The predicate is the “three-is-greater-than?” function, obtained by partially applying the curried greater-than function to the constant 3. This
SLIDE 28 question requires careful thought because a quick glance can make it seem like the code is testing whether something is greater than 3 rather than the
The greater-than function has to be curried before being applied to 3 because it otherwise takes two arguments at a time, not just one.
SLIDE 29
Composing Functions
In math, what is the following equal to? (f o g)(x) == ??? Another algebraic law, another function: (f o g) (x) = f(g(x)) (f o g) = \x. (f (g (x)))
SLIDE 30 One-argument functions compose
- > (define o (f g) (lambda (x) (f (g x))))
- > (define even? (n) (= 0 (mod n 2)))
- > (val odd? (o not even?))
- > (odd? 3)
#t
#f
SLIDE 31
Coding Interlude: compose
The predicate null? returns #t iff the argument list is empty, while the function not inverts a boolean. Use the compose function (o) to write a predicate that tests whether a list is non-empty. Run your code on both empty and non-empty lists.
SLIDE 32 Proofs about functions
Function consuming A is related to proof about A
- Q: How to prove two lists are equal?
A: Prove they are both ’() or that they are both cons cells cons-ing equal car’s to equal cdr’s
- Q: How to prove two functions equal?
A: Prove that when applied to equal arguments they produce equal results.