Title: CS
11321
2CS1321Introduction to Programming
- Georgia Institute of Technology
- College of Computing
- Lecture 17
- March 12, 2002
3Todays Menu
- Passing functions as parameters
- Or
- Now it gets interesting
- Review Adding parameters to generalize
functions - Passing code as values
- Contracts
- The Lambda function
4Last time
At the end of the last lecture, we started to
explore the idea of similarity in functionality
and how to program for that similarity. Our first
foray into this area of Computer Science dealt
with functions that dealt with the exact same
data types and very similar problem statements
Given a list-of-symbols, write a function
contains-doll? that determines whether or not the
symbol doll is contained in the list.
Given a list-of-symbols, write a function
contains-car? that determines whether or not the
symbol car is contained in the list.
5Similarities in Functions
As we develop more and more functions, one of the
things we start to notice (besides how sore our
fingers become) is just how much many of our
functions resemble each other. Theres always
that one little difference that makes it a
different function, however. So what if we
could get rid of that one little difference?
6It would be relatively trivial for us to write
individual functions that solved the problem
statement
Doll (define (contains-doll? in-los) (cond
((empty? in-los) false) (else (cond
((symbol? (first in-los) doll) true) (else
(contains-doll? (rest in-los)))))))
Car (define (contains-car? in-los) (cond
((empty? in-los) false) (else (cond
((symbol? (first in-los) car) true) (else
(contains-car? (rest in-los)))))))
7But as we see more functions with similar
functionality
Doll (define (contains-doll? in-los) (cond
((empty? in-los) false) (else (cond
((symbol? (first in-los) doll) true)
(else (contains-doll? (rest in-los)))))))
Bob (define (contains-Bob? in-los) (cond
((empty? in-los) false) (else (cond
((symbol? (first in-los) Bob) true)
(else (contains-Bob? (rest in-los)))))))
Truck (define (contains-truck? in-los) (cond
((empty? in-los) false) (else (cond
((symbol? (first in-los) truck) true)
(else (contains-truck? (rest in-los)))))))
Song (define (contains-song? in-los) (cond
((empty? in-los) false) (else (cond
((symbol? (first in-los) song) true)
(else (contains-song? (rest in-los)))))))
Car (define (contains-car? in-los) (cond
((empty? in-los) false) (else (cond
((symbol? (first in-los) car) true)
(else (contains-car? (rest in-los)))))))
Ball (define (contains-ball? in-los) (cond
((empty? in-los) false) (else (cond
((symbol? (first in-los) ball) true)
(else (contains-ball? (rest in-los)))))))
Orange (define (contains-orange? in-los)
(cond ((empty? in-los) false) (else
(cond ((symbol? (first in-los) orange) true)
(else (contains-orange? (rest in-los)))))))
8Déjà vu!
We come to realize that were writing the same
code over and over again. Heck, we might just be
copy-pasting our solutions and modifying whats
appropriate. And for those of you who have been
paying attention, youve seen what a mess that
can make of a perfectly good solution! So we
tried to recognize the pattern in our programs to
try to come up with our generic function
9Contains-ltvaluegt?
(define (contains-ltvaluegt? in-los) (cond
((empty? in-los) false) (else (cond
((symbol? (first in-los)
ltvaluegt) true)
(else (contains-ltvaluegt? (rest
in-los)))))))
If it comes down to this every time we write this
function, why dont we just pass a parameter for
the value were looking for?
10Our Solution
(define (contains-symbol? in-los in-symbol)
(cond ((empty? in-los) false) (else
(cond ((symbol? (first in-los)
in-symbol)
true) (else (contains-symbol?
(rest
in-los)
in-symbol))))))
11But wait!
You know, our last solution worked very well for
searching for some random symbol in a list of
symbols. But what about searching for a number
in a list of numbers, or a teaching assistant in
a list of teaching assistants? These are all the
same problem as searching for a symbol in a list
of symbols. Do we have a pattern we can follow?
12Compare and contrast
(define (contains-symbol? in-los in-symbol)
(cond ((empty? in-los) false) (else
(cond ((symbol? (first in-los)
in-symbol)
true) (else (contains-symbol? (rest
in-los)
in-symbol))))))
(define (contains-number? in-lon in-number)
(cond ((empty? in-lon) false) (else
(cond (( (first in-los)
in-number) true) (else
(contains-number? (rest in-lon)
in-number))))))
13Compare and contrast
(define (contains-symbol? in-los in-symbol)
(cond ((empty? in-los) false) (else
(cond ((symbol? (first in-los)
in-symbol)
true) (else (contains-symbol? (rest
in-los)
in-symbol))))))
Our biggest difference seems to lie in this area
in both functions the equality test.
(define (contains-number? in-lon in-number)
(cond ((empty? in-lon) false) (else
(cond (( (first in-los)
in-number) true) (else
(contains-number? (rest in-lon)
in-number))))))
14So whats our pattern?
(define (contains-ltvalue-typegt? in-list-of-type
value) (cond ((empty? in-list-of-type) false)
(else (cond ((ltgeneric equality
testgt
(first in-list-of-type)
value)
true) (else (contains-ltvalue-typegt?
(rest in-list-of-type)
value))))))
15So whats our pattern?
(define (contains-ltvalue-typegt? in-list-of-type
value) (cond ((empty? in-list-of-type) false)
(else (cond ((ltgeneric equality
testgt
(first in-list-of-type)
value)
true) (else (contains-ltvalue-typegt?
(rest in-list-of-type)
value))))))
If we had some way to create a generic equality
test, we could easily just insert it into our
pattern and be fine!
16We could
(cond ((number? value) lthandle numbersgt)
((symbol? value) lthandle symbolsgt)
((list-of-numbers? value) lthandle
list-of-numbersgt) ((list-of-symbols? value)
lthandle list-of-symbolsgt) ((posn? value) lthandle
posngt) ((shape? value) lthandle
shapegt) ((person? value) lthandle persongt) ((ta?
value) lthandle tagt) ((BT? value) lthandle
BTgt) ((BST? value) lthandle BSTgt) ((graph?
value) lthandle graphgt) ((list-of-persons? value)
lthandle list-of-personsgt) ((list-of-tas? value)
lthandle list-of-tasgt) ((fresh-fruit? value)
lthandle fresh-fruitgt) ((Georgia-student? value)
lthand them a mopgt)
Create a function called generic-equality that
took in both the values and their types and used
our various predicates such as number? or symbol?
to set up a massive cond statement to handle
each and every type that we could possibly need
17But
This would be cumbersome to the extreme! Wed
have to add new equality tests every time we
encountered a new type. In addition, what if we
didnt want to just check to see if our list
contained an item EQUAL to a target value? What
if we wanted to test to see if any of the items
in our list were greater than or less than a
given target value? This is still the same
pattern of code!
18As you were leaving
We started discussing a new concept in our
exploration of Computer Science passing
functionality as a parameter.
19And the code
How does this work? Scheme operates on a
relatively simple set of rules. One of those
rules is as follows
20If we see this interpret what follows
as a list of items. If we see this
Interpret what follows as a function call on a
list of Arguments.
(
(
21Examples
The list of , 1, 2 ( 1 2) The function
call on 1 2 ( 1 2) The list of symbol?,
a , b (symbol? a b) The function call
symbol? on a, b (symbol? a b)
22So
If Scheme has determined that it shouldnt
interpret what follows the parenthesis as a list,
it looks for the function definition that matches
the first name that follows the parenthesis.
Have you ever seen
when trying to do the following?
23Scheme is attempting to find a function body
associated with the name a!
24Our example
We can pass function bodies to our new function
and apply them to a set of arguments!
25Our original problem
Lets rename our function to contains?
(define (contains? in-test in-list value)
(cond ((empty? in-list) false)
(else (cond ((in-test (first in-list)
value) true) (else
(contains? in-test
(rest in-list)
value))))))
26Our original problem
Lets rename our function to contains?
(define (contains? in-test in-list value)
(cond ((empty? in-list) false)
(else (cond ((in-test (first in-list)
value) true) (else
(contains? in-test
(rest in-list)
value))))))
Let Scheme handle the problem of applying our
function to our arguments!
27Does it work?
Now we just have to define how we compare two
items of the same type and we have a working
search function.
28Big Picture
To make sure weve understood this example, lets
consider what weve been doing in the course so
far.
29Big Picture The Data
Thus, far, weve done extensive modeling of data.
Familiar diagrams were used to illustrate the
data models.
(cons a empty)
(define-struct book (pages isbn title
author)) (make-book 100 123
DasRepublic Plato)
30The Big Picture Functions
We also defined functions to use this data. We
can visualize what these functions might look
like
(define (area radius) ( radius radius pi))
(define pi 3.14)
3.14
31More Big Picture
In the past, weve called functions with data
(define pi 3.14) (define rad 15) (define (area
radius) ( radius radius pi)) (area rad)
3.14
15
32Thus
(define (contains? in-test in-list value)
(cond ((empty? in-list) false)
(else (cond ((in-test (first in-list) value)
true) (else (contains? in-test
(rest in-list)
value))))))
33Thus
(define (contains? in-test in-list value)
(cond ((empty? in-list) false)
(else (cond ((in-test (first in-list) value)
true) (else (contains? in-test
(rest in-list)
value))))))
(contains? symbol? (cons doll empty) doll)
( )
34Another example
Often times youll run across a problem that
takes in a data type such as a list and asks you
to create a new list containing a selection of
the original data that meets a certain criteria.
We mentioned two in the last lecture
35Write a function lower-than that takes in a
number and a list of numbers and returns a list
of numbers in which every value in our list is
SMALLER than the inputted number.
Write a function higher-than that takes in a
number and a list of numbers and returns a list
of numbers in which every value in our list is
LARGER than the inputted number.
We could alter these two problem statements to
ask for the selection of items equal to a given
number. We could change the problem such that it
deals with symbols, structures, entire lists, etc.
36The Common Thread
When we look at the solutions to the two problem
statements given on the previous slide, we begin
to see the pattern.
37(define (lower-than in-lon in-num) (cond
((empty? in-lon) empty) (else (cond ((lt
(first in-lon) in-num) (cons
(first in-lon) (lower-than (rest in-lon)
in-num))) (else (lower-than (rest in-lon)
in-num))))))
(define (higher-than in-lon in-num) (cond
((empty? in-lon) empty) (else (cond ((gt
(first in-lon) in-num) (cons
(first in-lon) (higher-than (rest
in-lon) in-num))) (else (higher-than (rest
in-lon) in-num))))))
38(define (lower-than in-lon in-num) (cond
((empty? in-lon) empty) (else (cond ((lt
(first in-lon) in-num) (cons
(first in-lon) (lower-than (rest in-lon)
in-num))) (else (lower-than (rest in-lon)
in-num))))))
Our common thread lies in our comparison
operator. In the lower-than function its a lt
comparison between the first item in our list and
the inputted number. In higher-than, its the
gt operator. If we were testing for equal, wed
substitute operator. To handle symbols, we
could insert symbol? where appropriate. For
structures, we could create our own equality
tests
(define (higher-than in-lon in-num) (cond
((empty? in-lon) empty) (else (cond ((gt
(first in-lon) in-num) (cons
(first in-lon) (higher-than (rest
in-lon) in-num))) (else (higher-than (rest
in-lon) in-num))))))
39So if we took away the specific operators in
our problems
(define (filter in-list in-target) (cond
((empty? in-list) empty) (else (cond
((ltGENERIC TESTgt (first in-list) in-target)
(cons (first in-list)
(filter (rest in-list) in-target))) (else
(filter (rest in-list) in-target))))))
This is the generic pattern of our functions.
Wed insert the specific test into the function
to create lower-than or higher-than
40The filter function
(define (filter in-test in-list in-target)
(cond ((empty? in-list) empty) (else (cond
((in-test (first in-list) in-target)
(cons (first in-list) (filter
in-test
(rest in-list)
in-target))) (else (filter in-test
(rest in-list) in-target))))))
41Last example map
In the last example, we took in a list data
structure and modified the shape of the list by
selecting a portion of its contents for the
result. Lets consider instead the case in which
we keep the shape of the list, but alter the
data contained within the list.
42Sample problem statements
Given a list of numbers representing a
temperature in degrees Celsius, generate a list
of numbers containing the equivalent temperature
in degrees Fahrenheit.
Given a list of TA structures (make-TA name
pay-rate worked) generate a list of symbols
containing the names of the TAs.
Given a list of TA structures (as defined above),
generate a list of numbers containing the amount
of pay received by each TA.
43Our solutions would look likeConverting to
Fahrenheit
(define (convertCF in-lon) (cond ((empty?
in-lon) empty) (else (cons ( ( (first
in-lon) 1.8) 32) (convertCF (rest
in-lon)))))
44Our solutions would look likeExtracting TA Names
(define (extract-name in-loTA) (cond ((empty?
in-loTA) empty) (else (cons (TA-name (first
in-loTA)) (extract-name (rest in-loTA)))))
45Our solutions would look likeCalculating TA
salary
(define (calc-salary in-loTA) (cond ((empty?
in-loTA) empty) (else (cons ( (TA-pay-rate
(first in-loTA)) (TA-worked (first
in-loTA))) (calc-salary (rest in-loTA)))))
46Where is the similarity?
In all three cases, were applying a certain
functionality on each and every item of our list.
We are then putting the result of this
functionality back on the list. This is also
known as mapping a functionality on every item in
our list. The only change we make in each case is
what we do with each value in the list before
putting onto our result. We can develop the
following generic function
47Map
(define (map functionality in-list) (cond
((empty? In-list) empty) (else (cons
(functionality (first in-list))
(map functionality
(rest in-list))))))
48Map
(define (map functionality in-list) (cond
((empty? In-list) empty) (else (cons
(functionality (first in-list))
(map functionality
(rest in-list))))))
49So how do you denote passing functionality in
your contract?
Passing functions as parameters adds all sorts of
complications to our Contract. We try as best as
possible to show what the expected types of the
values coming in should be, including functions
that are coming into our main function as
parameters. We denote function parameters as
contracts themselves
50contains? (X Y ? boolean) (listof X) Y ?
boolean
(define (contains? in-test in-list value) )
Breaking it down
(X Y ? boolean) a function that takes in
two arguments of unknown type and
produces a boolean (listof X) a shorthand
the book uses for list-of-X Y a value of
unknown type
51filter (X Y ? boolean) (listof X) Y ? (listof
Z)
(define (filter in-test in-list in-target) )
(X Y ? boolean) a function that takes in
two arguments of unknown type and
produces a boolean (listof X) a shorthand
the book uses for list-of-X Y a value of
unknown type (listof Z) a list of results
of unknown type
52map (X ? Y) (listof X) ? (listof Y)
(define (map functionality in-list) )
(X ? Y ) a function that takes in an
argument of unknown type and produces
a value of unknown type (listof X) a
shorthand the book uses for
list-of-X (listof Y) a list of results of
unknown type
53Questions?
54Moving on
So we understand the idea of going from this
(contains-number? ( 1 2 3 4 5) 6 )
A function which takes in a list of numbers and a
number.
55Moving on
To this
(contains? (1 2 3 4 5) 6)
A function which takes in a list of numbers, a
number, and some sort of functionality that acts
on our numbers within the body of the code.
56In our code
(define (contains? in-test in-list value)
(cond ((empty? in-list) false)
(else (cond ((in-test (first in-list) value)
true) (else (contains? in-test
(rest in-list)
value ))))))
Within the actual body of the code, we merely
applied the functionality passed in as an
argument to the first of our list and the value
passed in. This was made possible by exploiting
Schemes simple set of evaluation rules.
57This has implications
The ability to pass functionality as an argument
to another function has certain implications and
raises certain questions. 1) Just what does
(define (f x) ) really mean? 2) If we can
separate a functions actual
functionality from its name, is there a way just
pass function bodies?
58Lambda bodies
Besides being an oh-so recognizable symbol for
DrScheme, the image shown to the left (minus the
nifty coloring) is the greek symbol ? (lambda)
59Lambda
A lambda expression is nothing more than a
function body without a name.
60?
Lambda, in Scheme, represents a nameless function
body.
(lambda (x y) ( ( x 3) ( - y 2)))
This is a nameless function. It takes in two
arguments (x y), and performs a calculation on
those two arguments (x 3) (y 2).
61?
All semester long, weve seen that (define) will
bind a symbol to a function body.
Lambda allows us to create a function with no
name.
62Lambda
Scheme already does this. When we type (define
(square x) ( x x)) Scheme sees it
as (define square (lambda (x) ( x x)))
63Example
(define factorial (lambda (num) (if
(zero? num) 1 ( num
(factorial (- num 1))))))
A more traditional example of using no-name
functions.
64Lambda
So lets consider (define square (lambda (x)
( x x)))
The (lambda) part merely means heres a function
that takes in a parameter, called x, and performs
the following operations. This function,
identified by the lambda expression, is defined
as being the symbol square.
65Lambda
So lets consider (define square (lambda (x)
( x x)))
In short, the "lambda" tells Scheme to compile
the function body that follows, and return the
executable result. That is, lambda is like a
function that returns a function.
66Lambda
So lets consider (define square (lambda (x)
( x x)))
The name "lambda" itself comes from something
called "lambda calculus", the mathematical
precursor to functional programming that was
developed by Alonzo Church.
Read more The Advent of the Algorithm, David
Berlinski
67Strategy
So, when lambda is called, Scheme takes in some
code, compiles it, and returns an executable
function.
A compiled function
(Some code)
lambda
68?
Lambda, in Scheme, represents a nameless function
body.
(lambda (x y) ( ( x 3) ( - y 2)))
This example shows a nameless function. It takes
in two arguments (x y), and performs a
calculation on those two arguments,
(x 3) (y 2).
69? the syntax
Lambda has a very simple syntax
(lambda (parameter1 parameter2 parameter-n)
ltexpression to evaluategt)
(lambda (in-num) ( in-num 1))
(lambda (in-sym) (cond ((symbol? in-sym
a) true)
(else false)))
70? Our original questions
Back to our original questions
1) Just what does (define (f x) ltexpressiongt)
really mean?
(define (f x) ltexpressiongt) creates a function f
with a parameter x that evaluates ltexpressiongt.
But behind the scenes, we have the following
(define f (lambda (x) ltexpressiongt))
71? Our original questions
(define (convertCF in-lon) (cond ((empty?
in-lon) empty) (else (cons ( ( (first
in-lon)1.8) 32) (convertCF (rest
in-lon)))))
(define convertCF (lambda (in-lon)
(cond ((empty? in-lon) empty) (else
(cons ( ( (first in-lon)1.8) 32)
(convertCF (rest in-lon)))))))
THESE ARE EQUIVALENT!
72? Our original questions
2) If we can separate a functions actual
functionality from its name, is there a way just
pass function bodies?
Yep. If youll think back a bit
Here we are stripping away the functionality of
addition from the name and passing it as an
argument.
73? Our original questions
Here I pass in a nameless function body to
my-function.
74? Its not all sun and roses
Before you fall in love with the idea of
lambda-bodies and passing nameless functions,
remember that using functions in this manner has
its draw-backs 1) Less readable code! If you
spontaneously generate a lambda-body to
pass to another function, you include the
entire code for the lambda body in the
code! Clutter! 2) Names are more useful than
you think! Once youve sent a lambda-body
on its way, youve lost your handle on the
function. If you need to use the same
lambda-body in multiple places, youd have
to duplicate the code every time!
75Questions?
76(No Transcript)