University of California, Berkeley
EECS Department - Computer Science Division
CS3 Lecture 14 : Lambda
(Thanks to Oliver Grillmeyer and Brendan Ferguson
for many of the ideas in these notes)
Overview of today's lecture
Answers to questions
that have come up
- Do I have to use sent and wd as variable
names?
- As of today, when you are writing a procedure to handle GENERIC
words or sentences, you may use the shorthand w or s.
- If you don't have GENERIC words or sentences, you should
use more descriptive names.
- E.g., If I have a sentence of temperatures, instead of calling
the variable s, I should call it temps or temperatures.
Review
- Higher-order functions
- accumulate, a higher-order function which operates
on every word in a sentence
- repeated, a higher-order function which takes in
a function and a number and returns a function which is that
function applied that number of times.
Lambda
Introduction
- Lambdas are special forms which provide
a way of creating functions other than using define,
except you don't need to assign a name to them!
- Usage: (lambda (formal-parameters) body)
- The first element is the symbol lambda
- The second is a parameter list,
- The remaining elements are the body of the function (just
as in define)!
- Lambdas create nameless functions
- We've been using lambda all along, it was just being handled
automatically by the computer.
Example : square (aka
"The truth about define")
(define (square x)
(* x x))
- ...the Scheme interpreter automatically translates it to
(define square
(lambda (x) (* x x)))
- This means that the variable square is bound to
a procedure which takes an argument x, and multiplies
it by itself.
- lambda just means a procedure.
- It turns out, then, that a procedure name is really just
a variable whose value happens to be a procedure.
- We knew this already! What happens when we type:
: square
==>
- We don't have to give every function a name. I could call
a function by saying either
( square 3 ) ;; ==> 9
( (lambda (x) (* x x)) 3 ) ;; ==> 9
- The first parenthesis tells us we're calling a function,
and the second parenthesis is the one that denotes the beginning
of the function.
- The function is anonymous, all we know is it takes an argument
called x, and it multiplies that argument by itself.
Using lambda with multiple
(or no) arguments
- Functions returned by lambdas can take multiple
(or no) arguments, just as functions can.
- Example: A function that takes no arguments and returns cal:
: (lambda () 'cal)
#[procedure #x18F0794]
: ((lambda () 'cal))
cal
- Example: A function that takes two arguments and
: ((lambda (a b) (+ a b)) 4 5)
9
The truth about let
- You may notice that the way let stores a value in
a temporary variable is similar to the way lambda does
it.
- It turns out let is really an abbreviation for lambda.
- Example: notice the similarity between the lambda
above and this let:
: (let ((a 4)
(b 5))
(+ a b))
9
Name Conflicts : AVOID THEM!
- What happens when you have inner parameters (created by let,
lambda, etc) with the same name as the outer parameters (or as
a global variable)?
- Answer: Bad things, so AVOID THEM.
- In truth, the inner parameters win, the outer values are
shadowed, and not seen inside.
- Example:
(define (foo x)
(let ((x 3))
(lambda (x)
(+ x 5)))) ;; Which x do we mean?
Lambda and Higher-Order
Functions
Overview
- More useful than the above is using lambda with higher-order
functions.
- That is, instead of saying
: (define (square x) (* x x))
square
: (every square '(1 2 3 4))
(1 4 9 16)
- I could write it more succinctly like this:
: (every (lambda (x) (* x x)) '(1 2 3 4))
(1 4 9 16)
- I eliminated the step of having to separately define square,
by just writing literally the function I want to do to every
word in the sentence.
- I just cut out the middle man because the only time I'm going
to need that function is just for this one call to every,
and I'm not going to need to refer to it again.
- The only time I need to name a function is when I'm going
to need to use it more than once, for the same reason that I
only create any variable if it refers to a value I need more
than once.
- Recall the definition
(define square (lambda (x) (* x x))).
- It means that any time I see the word square, I
could replace it with
(lambda (x) (* x x))
- That's just what I did in the call to every above.
I replaced the word square with its value, which is
that procedure
Example : add-1-to-sent
- Let's do a more extended example to illustrate lambda's
importance.
- Add 1 to every word in a sentence, and return a sentence
of the results
- Here's the long way
;; add-1-to-sent
;;
;; Example: (add-1-to-sent '(1 2 3)) ==> (2 3 4)
(define (add-1-to-sent S)
(every add-1 S))
(define (add-1 num)
(+ num 1))
- ...and here's the short way...
(define (add-1-to-sent S)
==>
- I don't need to go to the bother of defining a separate function
called add-1 to add 1 to a number, I can just use lambda.
- You might, however, say that using lambda explicitly
may be shorter, but it's still unnecessary. Consider the following
example:
Example : add-n-to-sent
- What about if someone asked you to write a function to add
an input, n, to a sentence of words:
;; add-n-to-sent
;;
;; Example: (add-n-to-sent 5 '(1 2 3)) ==> (6 7 8)
(define (add-n-to-sent n S)
(every ??? S))
;; What goes in the ??? -- let's try to find out.
- My first try in which I try the old-fashioned way of using
a helper function
(define (add-n-to-sent n S)
(every add-n S))
(define (add-n num)
(+ num n)) ; WRONG, why? ==>
- So I try to fix it like this:
(define (add-n n num) ; I added a new parameter called n
(+ n num)) ; ALSO WRONG, BUT FOR A DIFFERENT REASON
; Why? ==>
- In fact, I cannot write a separate function add-n
if I want to use every.
- There's no way that it can add n to the number,
because it doesn't know the value of n.
- The solution is to ditch the helper function altogether and
use lambda instead.
(define (add-n-to-sent n L)
==>
- This works because the lambda only takes one argument,
but it can still refer to n within its body because
n is a parameter of the current function.
Example : add-1-to-odds
- Given a sentence, return the same sentence with all the odd
numbers incremented by 1
;; Example:
;;
;; (add-1-to-odds '(1 out of 3 likes u 2 and u b 40))
;; ==> (2 out of 4 likes u 2 and u b 40)
: (define (add-1-to-odds S)
==>
==>
==>
==>
- Is lambda just convenient or is it necessary?
==>
Example : all-letter-twister?
- Given a letter and a sentence, return non-#f if
every word in the sentence is a begins with a given letter (i.e.,
is a tongue twister in that latter), otherwise #f
;; Example:
;;
;; (all-letter-twister? 'r '(rubber bumper baby buggy)) ==> #f
;; (all-letter-twister? 's '(six sheiks sixth sheeps sick)) ==> #t
: (define (all-letter-twister? letter S)
==>
==>
==>
==>
- Is lambda just convenient or is it necessary?
==>
Summary
- Lambda expressions are a way of creating nameless functions.
- They are most often used to create specialized functions
to use with higher-order functions.
- You sometimes NEED lambdas when the function you are passing
in as an argument to the functional needs more information than
just each list element provides.
- They are the easiest way to return a function
Next Time
- Mo Lambda Mo Lambda Mo Lambda!
Puzzle : Baseball batting averages (as
heard on CarTalk)
- There are two rookie players, Bluto and Popeye, who started
the season on opening day and made a wager as to which one would
have the better batting average at the end of the season.
- Well, the last day of the season arrives, and not much is
going to change, especially considering that neither one of them
is in the starting lineup.
- Bluto says, "Hey, Popeye, what did you bat for the first
half of the year?"
- Popeye answers, "I batted .250."
- And Bluto responds, "Well, I got you there. I batted
.300. How about after the All-Star break?"
- Proudly, Popeye pipes up, "I batted .375."
- Bluto says, "Pretty good, but I batted .400. Fork over
the 20 bucks that we bet."
- The batboy, Dougie, saunters over and says, "Don't pay
the 20 bucks, Popeye. I think you won."
- How could Popeye have won?
Game : Kayles [BerlekampConwayGuy82]
- Kayles is an old English game.
- You have a row of bowling pins set up.
- On your turn you can bowl and knock down either one or two
adjacent pins.
- The person who is unable to knock down a pin (meaning they
have all fallen) loses.
References
- [BerlekampConwayGuy82] Elwyn Berlekamp, John H. Conway, Richard
K. Guy "Winning Ways for Your Mathematical Plays",
Academic Press, London, 1982.
WWW Maven: Dan
Garcia (ddgarcia@cs.berkeley.edu)
Send me feedback