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.
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.complementis 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.darkeris 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.redderis 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
(rgb.red c). Putting that together, we might
write the following for
(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
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
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.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
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
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
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
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.
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
You may wish to validate this document's HTML ; ;Samuel A. Rebelsky, email@example.com
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.