Fundamentals of Computer Science I: Media Computing (CS151.02 2007F)
[Skip to Body]
Primary:
[Front Door]
[Glance]
-
[Academic Honesty]
[Instructions]
Current:
[Outline]
[EBoard]
[Reading]
[Lab]
[Assignment]
Groupings:
[Assignments]
[EBoards]
[Examples]
[Exams]
[Handouts]
[Labs]
[Outlines]
[Projects]
[Readings]
[Reference]
Reference:
[Scheme Report (R5RS)]
[Scheme Reference]
[DrScheme Manual]
Related Courses:
[CSC151.01 2007F (Davis)]
[CSC151 2007S (Rebelsky)]
[CSCS151 2005S (Stone)]
This reading is also available in PDF.
Summary: We examine how one writes procedures, particularly in the context of writing image filters. These procedures are anonymous
in that we do not need to name them.
Contents:
In the recent readings on transforming RGB colors and transforming images, you learned about some basic functions that transform colors and how to extend those functions to transform images. When use a function to transform a whole image, we call the process a filter for an image.
While the basic functions provide you with a wide variety of capabilities, they are still somewhat limited. For example, it is difficult or impossible to use them to convert an image to greyscale, to increment the red component by 21, and a huge variety of other things.
For such activities, we need to write our own filters. Writing those filters is the subject of this reading.
As you may recall, at the center of any filter (or at least any filter we've written so far) is a function that transforms one color to another. Let's think about how we might describe some of the color transformations we've learned so far.
rgb.complement is a function that, given a color, c, computes
a new color whose red component is 255 minus the red component of c, whose
green component is 255 minus the green component of c, and whose blue
component is 255 minus the green component of c.
rgb.darker is a function that, given a color, c, computes
a new color whose red component is 16 less than the red component of c
(or 0, if that expression is negative), whose green component is
16 less than the green component of c (or 0, if that expression is
negative), and whose blue component is 16 less than the blue
component of c (or 0, if that expression is negative).
rgb.redder is a function that, given a color, c, computes
a new color whose red component is 8 more than the red component of c
(or 255, if that expression is greater than 255), whose green component
is the green component of c, and whose blue component is the blue
component of c.
If the original color, c, had been named with
define, and our goal was simply to define a new name,
newcolor, we could use the techniques that we've
covered so far. In particular, when we say compute a new color
we can use
rgb.new and when we say the red component of
we can use c(rgb.red c). Putting that together, we might
write the following for rgb.complement.
(define c ...) (define newcolor (rgb.new (- 255 (rgb.red c)) (- 255 (rgb.green c)) (- 255 (rgb.blue c))))
But that pair of defines aren't a function. That is, the defines do not
constitute the kind of code that we can, for example, pass as a parameter
to image.transform-pixel!, image.map!, or
image.map. To write Scheme functions for each
of these algorithms, we must also translate the a function that, given
a color, c
. In Scheme, you write that as
(lambda (c) ...)
For example, we could express the complement transformation as
(lambda (c) (rgb.new (- 255 (rgb.red c)) (- 255 (rgb.green c)) (- 255 (rgb.blue c))))
We can certainly use any name we want for the original color. For example, here's a definition of redder that uses nre (not red enough) as the name of that color.
(lambda (nre) (rgb.new (min 255 (+ 8 (rgb.red nre)) (rgb.green nre) (rgb.blue nre))))
Note that we have not given this version of the function a name. It is just a function that, when given a color,
. Since the function has no explicit name, we call it an
anonymous function.
nre, computes a new color by adding eight to the red component and leaving the other two components unchanged
Okay, what good are these anonymous functions? Well, we can use
them in any procedure that expects another procedure as a parameter.
In particular, we can use them with image.transform-pixel!,
image.map!, and image.map. At present, we
will use them most frequently with the mapping functions.
For example, here's a filter that sets the red component of every pixel
in picture to 0.
(image.map! (lambda (c) (rgb.new 0 (rgb.green c) (rgb.blue c))) picture)
Similarly, here's a filter that sets the blue component to 0.
(image.map! (lambda (c) (rgb.new (rgb.red c) (rgb.green c) 0)) picture)
Here's a slightly more complex filter that sets the green component to the average of the green and blue components.
(imagemap! (lambda (c) (rgb.new (rgb.red c) (/ (+ (rbg.blue c) (rgb.green c)) 2) (rgb.blue c))) picture)
Okay, we've seen a bit about functions and how one might use them. What does the general case look like? In Scheme, we most typically specify a function by writing
lambda,
That is, it looks like
(lambda (param0 param1 ... paramn) expression)
The expression can use any names given in the parameter list, as well
as any other names known to Scheme, such as those given by previous
define commands.
Although we have only written functions that transform colors (so far), in Scheme anything (more or less) can be a parameter to a function.
Using a Greek letter to mean function
is a bit odd, but it's
a tradition dating back to Alonzo Church, a mathematician who, in the early
20th century, studied how mathematicians think. (Church was also Rebelsky's
great great grand-advisor.)
Particularly when you use operations like image.map, which
expect another function as a parameter, it is convenient to just plug in
the description of a function when you want to do something. However, at
other times, you will find it handy to name the functions you create. How
do you name functions? The same way you name anything in Scheme, with
define. For example, here's one of the sample color
transformations, named appropriately.
(define no-red (lambda (c) (rgb.new 0 (rgb.blue c) (rgb.green c))))
We will return to the techniques and benefits of naming functions in a future reading and laboratory.
http://www.cs.grinnell.edu/~rebelsky/Courses/CS151/History/Readings/anonymous-procedures.html.
[Skip to Body]
Primary:
[Front Door]
[Glance]
-
[Academic Honesty]
[Instructions]
Current:
[Outline]
[EBoard]
[Reading]
[Lab]
[Assignment]
Groupings:
[Assignments]
[EBoards]
[Examples]
[Exams]
[Handouts]
[Labs]
[Outlines]
[Projects]
[Readings]
[Reference]
Reference:
[Scheme Report (R5RS)]
[Scheme Reference]
[DrScheme Manual]
Related Courses:
[CSC151.01 2007F (Davis)]
[CSC151 2007S (Rebelsky)]
[CSCS151 2005S (Stone)]
Disclaimer:
I usually create these pages on the fly
, which means that I rarely
proofread them and they may contain bad grammar and incorrect details.
It also means that I tend to update them regularly (see the history for
more details). Feel free to contact me with any suggestions for changes.
This document was generated by
Siteweaver on Mon Dec 3 09:53:18 2007.
The source to the document was last modified on Wed Sep 12 16:51:31 2007.
This document may be found at http://www.cs.grinnell.edu/~rebelsky/Courses/CS151/2007F/Readings/anonymous-procedure-reading.html.
You may wish to
validate this document's HTML
;
;
http://creativecommons.org/licenses/by-nc/2.5/
or send a letter to Creative Commons, 543 Howard Street, 5th Floor,
San Francisco, California, 94105, USA.