Higher-Order Functions and Function Composition, with Processing

I was looking for a good way to illustrate functional composition and higher order functions, and thought that something could be done with Processing, a java-based graphics tool. Among other things, Processing exposes raw pixel data for the images it renders, and you can update the pixels programatically, providing a simple kind of image filtering.

For example, here’s some code that converts a color image to grayscale. Just like with HTML, colors are represented1 as 3 channels (red, green, blue), and each channel has 255 increments. A gray pixel has equal amounts of red, green, and blue, so if you get the overall brightness of a pixel, and set its color to that much red, green, and blue, it should turn the image gray.


PImage img = loadImage("tattoo.jpg");
size(img.width, img.height);  // set the window size
image(img, 0, 0);  // render the image at x:y = 0:0

loadPixels(); // load the image's pixels into an array
for (int i = 0; i < pixels.length; i++) {
    // get the color for this pixel
    color c = pixels[i];

    // get its brightness
    float bright = brightness(c);

    // Change its color to its grayscale equivalent
    pixels[i] = color(bright, bright, bright);
}
updatePixels();  // render the new pixels to the screen

Here’s the original image:

the original image

…and here’s the filtered version:

the image in grayscale

You can define a bunch of routines like this, each looping through the pixels the same way, but adjusting the colors differently. But if you can separate the pixel-changing part from the pixel-looping part, then you can swap in ANY pixel-changing routine, giving you a flexible image filtering system.

The pixel-changing code is essentially a function that turns one pixel’s color into a new color, and the pixel-looping code uses it to replace each pixel’s original color. The pixel-changing function could be described like this:


color transform(color c) {
    ...
}

Many modern programming languages support first-class functions, which are a natural way to model this. Processing uses a form of Java, which doesn’t have first-class functions, but we can wrap the functions in a class, giving us an object called a functor. I called this one ColorTrans, for “color transformer”.


abstract class ColorTrans {
    public abstract color transform(color c);
}

The ColorTrans class’ only method, transform, is our pixel-changing function. We can re-write the loop from before to use a ColorTrans filter, and while we’re at it, we’ll move it into a method that takes the filename as a parameter, too.


void filterImage(String path, ColorTrans filter) {
    PImage img = loadImage(path);
    size(img.width, img.height);
    image(img, 0, 0);

    loadPixels();
    for (int i = 0; i < pixels.length; i++) {
        // use the filter parameter
        pixels[i] = filter.transform(pixels[i]);
    }
    updatePixels();
}

We can easily recreate the grayscale filter from earlier as a ColorTrans.


ColorTrans grayscale = new ColorTrans() {
    color transform(color c) {
        float bright = brightness(c);
        return color(bright, bright, bright);
    }
};

filterImage("tattoo.jpg", grayscale);

Another really easy filter to write is an inverter. If a pixel has R:100, G:30, B:255, an inverter will return the color R:(255-100), G:(255-30), B:(255-255), or R:155, G:225, B:0.


ColorTrans invert = new ColorTrans() {
    color transform(color c) {
        return color(255 - red(c),
                     255 - green(c),
                     255 - blue(c));
    }
};

filterImage("tattoo.jpg", invert);

The image produced by an inverter is like a film negative.

inverted, like a negative

Now we begin to see the benefits of keeping the-parts-that-change separate from the-parts-that-don’t: we can easily define and swap in new filters. This is one of the big parts of higher-order programming: writing routines that are configured by passing in functions (or functors, in this case) to do part of the work.

Manufacturing a ColorTrans

A useful kind of filter is one that increases (or decreases) the color on one channel: add some red, or remove some green. This kind of filter is easy to create:


ColorTrans aFifthMoreRed = new ColorTrans() {
    color transform(color c) {
    	return color(red(c) * 1.2, green(c), blue(c));
    }
};

This filter will increase the amout of red in the image by 20%. But 20% is a pretty arbitrary number; it’d be better if we could tell the filter how much to increase the red by. Generally, you’d add an “amount” parameter to the transform method, but then filterImage would have to know that this ColorTrans object takes an extra parameter. It’s kind of nice having filterImage treat all ColorTrans objects the same, just passing in the color.

Instead, we can make a method that builds ColorTrans objects: we tell it how much to increase the red by, and it builds a ColorTrans that does it for us.


ColorTrans ampRed(final float amount) {
    return new ColorTrans() {
        color transform(color c) {
            color(red(c) * amount, green(c), blue(c));
        }
    };
}

ColorTrans aQuarterMoreRed = ampRed(1.25);
ColorTrans aThirdLessRed = ampRed(2/3);
ColorTrans noRedAtAll = ampRed(0);

(If you’re curious why amount is final, the short answer is “because the compiler says so,” but there’s a better answer2.)

This is pretty nice, because we can use this inside an animation loop, animating the amount of color amplification.


float theta = 0.0;

void setup() {
    filterImage("tattoo.jpg", noChange);
}

void draw() {
    float ampRedAmount = sin(theta) * 1.2;
    filterImage("tattoo.jpg", ampRed(ampRedAmount));
    theta += 0.1;
}

[Here's where I'd link to the applet, nicely hosted somewhere, if I had a hosting service that allowed applets. I'll try to find a place to put all the code, so you can try it yourself.]

Processing calls setup to initialize the animation, and calls draw once per “tick”, to advance the animation. Here, in each frame of the animation, a new ColorTrans is constructed by ampRed, with the amount tied to the sine wave function, oscillating between 0 and 1.2. When viewed, the amount of red in the image swells and falls, and back again3.

This is another big part of higher-order programming: writing functions that build other functions, based on some arguments. Combined with routines that take functions as arguments, it’s a handy way to break down some problems. If done well, the routines that take functions as arguments, and the functions that build those functions, can become a sort of mini-language, a fluent interface, or almost an embedded DSL.

Plugging filters together – filter composition

This is where it gets fun. Suppose you’ve created an ampBlue that works just like ampRed, and now you want to filter an image with both of them. One approach might be something like this:


void draw() {
    filterImage("tattoo.jpg", ampRed(sin(theta) * 1.2));
    filterImage("tattoo.jpg", ampBlue(cos(theta) * 1.2));
}

Using the sine and cosine functions, the image should pulse nicely through reds and blues. The only problem is that it doesn’t really work, because filterImage loads the image fresh from the filesystem each time, so you only get the effect of the ampBlue filter. So how can we apply multiple filters?

We plug them together. We want a filter that does the work of two other filters, and we want it to look like any other filter, so filterImage won’t know the difference. To get this, we can add a method to ColorTrans that returns a new ColorTrans, which calls first the one, and then the other.


class ColorTrans {
    ...
    public ColorTrans then(final ColorTrans applySecond) {
        final ColorTrans applyFirst = this;
        return new ColorTrans() {
	    color transform(color c) {
	        return applySecond(applyFirst(c));
	    }
	};
    }
}

filterImage("tattoo.jpg", grayscale.then(invert));

first grayscaled, then inverted

Combining filters becomes a matter of chaining them together through then. The red-and-blue example becomes:


void draw() {
   filterImage("tattoo.jpg",
        ampRed(sin(theta) * 1.2).then(
            ampBlue(cos(theta) * 1.2)));
}

Processing does it kind of this way, too

If you look at the source for Processing, in PImage.java on line 619, you’ll find code that looks kind of like this:


  public void filter(int kind) {
    loadPixels();

    switch (kind) {
      case BLUR: ...
      case GRAY: ...
      case INVERT: ...
      case POSTERIZE: ...
      case RGB: ...
      case THRESHOLD: ...
      case ERODE: ...
      case DILATE: ...
    }
    updatePixels();  // mark as modified
  }

It basically does just what I’ve been doing, except the operations are hard-coded into the source, rather than being separated behind a class interface. The filters aren’t composable directly, though you can call a number of them in a row:


filter(INVERT);
filter(THRESHOLD);
filter(DILATE);

One benefit of this approach is that it’s easy to see, line-by-line, exactly what’s happening. I’d bet it beats the pants off of the ColorTrans version in benchmarks, too. But filters aren’t composeable, and it’s certainly not extendable. When you’re doing computation-intensive graphics, every bit of speed is important; when you’re illustrating a programming idea, it’s not. Decide for yourself which is more important for your needs.

____________________________________


1. It may seem weird, if you know Java, that the parameter’s type is color — it’s not a java primitive, but it doesn’t follow the normal classname conventions. It’s just the way Processing does it. You can read more about the color constructor in the Processing reference. [back]


2. Taken from the AnonymousInnerClasses page on the Portland Patterns Repository, 2009-04-30:

AnonymousInnerClasses can also be used to create something like closures in the JavaLanguage. However they do not “close over” the lexical environment so they aren’t TrueClosures. (They can capture the value of local variables, but they do not have access to the variable binding so they can’t change the original variable. Which Java makes quite clear by only allowing InnerClasses to refer to local variables that have been declared final (so no-one can change them)).

[back]


3. The noChange filter returns the same color it was given — an identity function. filterImage is called inside setup only so the window size is set correctly, since setting the size inside draw has no effect. And theta is just a Greek letter often used for angles and trigonometry.[back]

Book Review: Pragmatic Thinking and Learning

I was planning on reading Andy Hunt’s Pragmatic Thinking and Learning: Refactor Your Wetware for a while, but kept putting it off, thinking it wasn’t really central to what I’m interested in, what I’m doing.  I was wrong.

People have different skill levels, from novice to expert.  One sign of expertise is the ability to intuit solutions not available through linear thinking.  Intuition happens on the right side of the brain, so we need to use the right side more effectively.  Rather than “left brain” and “right brain”, he calls them “L-mode” and “R-mode”, for “linear” and “rich”, to emphasize that it’s not literally two halves of your brain working differently, but two different modes of thinking.  Most of the book is about using R-mode more, and using L-mode appropriately, to fact-check your R-mode.

It draws on psychology, neurobiology, cognition studies, managing, teaching, the arts, product design, and math.  The bibliography is ten pages long, and I’ve got a bunch of them highlighted for my next evening at the bookstore.

The most valuable changes I’ve made since finishing the book are:

- Be ready when your R-mode strikes. Since “querying” the R-mode can take a long time, we run it asynchronously, and we never know when the results will come in.  (This explains the “ah-ha!” moments in the shower, on the drive home, and when you’re falling asleep.)  So keep a notebook handy for writing things down.  I’m writing in a notebook almost daily (I’ve joined the cult of moleskine), writing down ideas as they come up.  It’s also a tider home for all the scraps of paper that have lived in my wallet for years, ideas scrawled and smudged into them.  And I’m on my 4th or 5th pocket mod.

- Maintain your ‘exo-cortex,’ your external memory. I wrote a mini-wiki engine with Sinatra, and so far, I’ve used it for everything from clojure, to saving quotes, to robot rights.  I wrote it for practice, but it’s nice to have a searchable, non-linear notebook.

The book mentions Gerald Weinberg’s fieldstone method of writing: to build a stone wall, you gradually gather stones from the field as you clear it, and pile them up.  When you have enough, build your wall.  Both the wiki and the notebook serve this purpose.

- Map out your thinking, and doodle. Drawing pictures engages your R-mode, making it more active, helping you make connections, and understand more clearly.  Besides, it’s fun. This is my 3rd time learning emacs, and it’s finally sticking — I think it’s mostly because I drew up a cheat-sheet, pictorially explaining each command’s effect.  I also map out my learning and career goals this way.

emacs cheat sheet

One of my favorite parts is, after you’ve mapped something out, and the drawing looks like a pile of yarn, re-draw it on a clean sheet, fixing up all the awkward placements and messy bits.  The benefit of this second version is in its creation — by considering how to re-organize it, you’re thinking more about the problem, in ways you might not have before.  This works for note-taking, too.

- Take advantage of your brain’s plasticity. You can change how your brain works by believing it works differently: make it smarter, more creative, cheerier.  This is a pretty incredible claim, but he cites two books I’d like to check out.  It sounds impossible, but I’ve seen it work on me, to some extent.  My biggest problem is continuing to believe it works.

Some things I have yet to try:

- Take a walk.  A meditative walk, like around a labyrinth.

- Write morning pages: for three weeks, as soon as you wake, write down three pages of text.  It doesn’t have to be anything specific.  The idea is, right after we wake, our R-mode is more active, so the gems will be more accessible, and they’ll pop out onto the page.  I’m more curious to see what I come up with.

- I have to get better at setting SMART goals: specific, measurable, achievable, relevant, and time-boxed.  I’ve never been much for this kind of discipline — I made a few, but didn’t stick to them, and haven’t gotten into the habit yet.  But like the book says, change is hard:

Change is always harder than it looks — that’s a physical reality, not just an aphorism. An old, ingrained habit makes the equivalent of a neural highway in your brain. These old habits don’t go away. You can make new neural highways alongside, going a different route and making short-cuts, but the old highways remain. They are always there for you to revert to—to fall back on. Practice may not make perfect, but it sure makes permanent.

Heading to the Int’l Lisp Conf, 2009

My next step on the road to lisp is at the International Lisp Conference in Cambridge, MA, this March.

A lot of people are surprised to hear I’m interested in Lisp, but I’ve been studying scheme informally for about 3 years, reading SICP, and finishing The Little Schemer last year. I’ve been interested in clojure for about 18 months, especially after seeing Rich Hickey talk about it last March.  Now I’m studying it in earnest with Stu Halloway’s Programming Clojure.

I don’t use lisps of any sort at work, so it’s not a “practical” language to study like, say, C# is.  But that’s short-term thinking.  Learning lisp is plenty practical, if you’re looking longer-term — even if it’s only three years out.  Learning lisp teaches you about some of the core issues of programming.

I like learning lisp because it’s a window into the workings of programming languages, being so close to the AST.  I want to learn more about meta-programming with macros, hygienic or not.

And for the record, the functional techniques in The Little Schemer have improved my Ruby, JavaScript, and C# in some really solid ways. Functional programming is making its way to the rest of the programming world, and lisp does functional programming.

If you’ll be at the conference, I’d love to hear from you.

Come to the Hartford Ruby Brigade’s January Meeting

As we trudge back to our regular schedules after assorted holiday debaucheries, here’s a heartening thought: Hartford.rb is meeting on Monday, 1/26! Gary Wright will tell us the story of how he learned Git, and some lucky stiff will walk away with a free copy of The Rails Way. We’ll even have pizza — though we’re now on the look-out for a pizza sponsor, so if you know anyone looking to feed us (for only ~$50 a month!), it might even be free.

The usual details:
Monday, 1/26, 6 – 8 PM
GeeZeo
750 Main St, Hartford

See you soon.

Accuracy and Precision: Not the Same

I often hear people mis-use the words accuracy and precision, but they mean different things.

To say I’m 117 years, 93 days, 4 hours, 17 minutes, and 48.249 seconds old is very precise, but it’s inaccurate (right now, anyway).  To say I’m in my thirties is accurate, but imprecise.  Precision is about level of detail, accuracy is about truthiness.

They make a wonderful pair, working pretty much orthogonally to each other.

Wikipedia has a nice analogy using a bulls-eye target.

The Twelve Bugs of Christmas, via Ruby

Here’s a little bit of post-Christmas fun, based on the Twelve Days of Christmas.


bugs = %{
     Tell them it's a feature
     Say it's not supported
     Change the documentation
     Blame it on the hardware
     Find a way around it
     Say they need an upgrade
     Reinstall the software
     Ask for a dump
     Run with the debugger
     Try to reproduce it
     Ask them how they did it and
     See if they can do it again.
}.strip.split("\n").map { |bug| bug.strip }.reverse

days = %w[first second third fourth fifth sixth seventh eighth ninth tenth eleventh twelfth]

0.upto(11) do |day_num|
  puts "For the #{days[day_num]} bug of Christmas, my manager said to me"
  day_num.downto(0) do |bug_num|
    puts bugs[bug_num]
  end
  puts
end

Simplifying Boolean Expressions

(Apologies if this material seems elementary, but I’ve found enough code to make me think it should be talked about.)

I found some C# today that looked kind of like this.


if (someCondition) {
    return true;
}
return false;

This code says the author missed some key points about booleans. You can find it in almost any language.

Any code that fits into an if or while eventually becomes a boolean.  Using an if to “return true, else false” is redundant — just return the condition. That code can be simplified down to this one-liner:


return someCondition;

The same goes for assigning a variable. This:


bool result = false;
if (someCondition) {
    result = true;
}

…is the same as this:


bool result = someCondition;

(If you feel the longer version is clearer, as some do, I respectfully disagree with you, but that’s a different point, and I’m not interested in debating preferences.  You can probably stop reading here, but thanks for stopping by.)

What if your boolean values are swapped? You can invert your condition:


if (someCondition) {
    return false;
}
return true;

// is the same as:
return !someCondition;

As the nesting gets deeper, it gets hairier, but it can still be tamed:


if (condition1) {
    if (condition2) {
        return true;
    }
    return false;
}
return false;

// is basically:
return condition1 && condition2;

And…


if (condition1) {
    return true;
}
else if (condition2) {
   return true;
}
else {
   return false;
}

// is just:
return condition1 || condition2;

There are many other ways to tame a wild boolean — follow that link, and check the first table. It’s like simplifying an algebraic equation: x+0 is always x, and y && true is always y.

An Example

Let’s work through a contrived, yet nasty, example, to see how some of this works.


function contrivedYetNasty(hasYirmish, isNingle, amount) {
    var tooMuch = false;
    if (amount > 100) {
        tooMuch = true;
    }

    var foo = false;
    if (hasYirmish == false) {
        if (!!tooMuch) {
          foo = true;
        }
        else {
          foo = false;
        }
    }
    else {
        foo = true;
    }

    if (isNingle == true) {
        if (foo == false) {
            return false;
        }
        else {
            return true;
        }
    }
    else {
        return false;
    }
}

I have no idea what this does, but it’s nasty (which is often the situation with legacy code). These handy unit tests tell us how it behaves:


assert(false, contrivedYetNasty(false, false, 0))
assert(true,  contrivedYetNasty(false, true, 110))
assert(false, contrivedYetNasty(true, false, 0))
assert(true,  contrivedYetNasty(true, true, 110))  

assert(false, contrivedYetNasty(false, false, 0))
assert(true,  contrivedYetNasty(false, true, 110))
assert(false, contrivedYetNasty(true, false, 0))
assert(true,  contrivedYetNasty(true, true, 110))

First, let’s tackle tooMuch. It’s false, but if amount is over 100, then it’s true. If it always has the same truthiness as amount > 100, then it’s equivalent to amount > 100. Let’s write it that way.


var tooMuch = amount > 100;

The tests pass.

Next, let’s look inside the if (hasYirmish == false) block, lines 9 – 14 in the original. First, !!tooMuch is a double-negative: the first ! cancels out the second. We can just say if (tooMuch). “If tooMuch is true, foo is true; else (if tooMuch is false), foo is false.” So foo is the same as tooMuch, and we can rewrite the block like this:


if (hasYirmish == false) {
    foo = tooMuch;
}
else {
    foo = true;
}

Tests pass.

“If hasYirmish is false, foo is tooMuch; else, foo is true.” This is just like a boolean OR expression. When a || b is evaluated, if a is true, the expression evaluates to true, without even checking b; but if a is false, then the expression evaluates to the value of b. And that’s exactly what we want here. That block just becomes:


var foo = hasYirmish || tooMuch;

The tests still pass. So far, we’re down to this:


function contrivedYetNasty(hasYirmish, isNingle, amount) {
    var tooMuch = amount > 100;
    var foo = hasYirmish || tooMuch;

    if (isNingle == true) {
        if (foo == false) {
            return false;
        }
        else {
            return true;
        }
    }
    else {
        return false;
    }
}

Not bad!

Inside the isNingle == false block, on lines 6 – 11 above, we have: “if foo is false, return false; else (if it’s true), return true.” Again, we just want to return the value of foo. Let’s re-write it that way, test it (they pass), and take a look at the isNingle == true block.


if (isNingle == true) {
    return foo;
}
else {
    return false;
}

Now, we have a similar situation to when we introduced the OR expression, but it’s slightly different. If isNingle is false, the whole thing is false; if it’s true, then it’s the value of foo. Sounds like an AND expression. Let’s try it.


return isNingle && foo;

The tests still pass. Let’s step back and look at our progress:


function contrivedYetNasty(hasYirmish, isNingle, amount) {
    var tooMuch = amount > 100;
    var foo = hasYirmish || tooMuch;
    return isNingle && foo;
}

From 31 lines down to five, and it’s actually readable. We can in-line those variables, and it gets even clearer:


function contrivedYetNasty(hasYirmish, isNingle, amount) {
    return isNingle && (hasYirmish || amount > 100);
}

It returns true “if isNingle, and either it hasYirmish, or amount is over 100.” Much better.

Beyond the Basics

Once you’re comfortable with simplifying boolean expressions, there’s a number of rules you can employ to refactor nastier boolean expressions. Most of them are easy to remember, and can be easily illustrated in real-life terms. Meet DeMorgan:

  • !(a || b) == !a && !b. “It’s not red or green” is the same as “It’s not red, and it’s not green.”
  • !(a && b) == !a || !b. “I’m not rich and handsome” is true if I’m not rich, OR if I’m not handsome. (Or if I’m neither.)

These rules are part of a larger topic called Boolean algebra, which is useful for simplifying circuits, and (of course) programming. At my university, Boolean algebra was taught in Discrete Math, which was required for CS majors. Maybe programmers without a CS degree have a harder time with booleans because they missed this class, but the good news is, it’s easy enough to pick up.

Next Hartford Ruby Group meeting: 11/24

The Hartford Ruby Group is meeting this Monday, 11/24, from 6 – 8 PM.

Flinn Mueller will be talking about rspec, and we’ll hopefully hear stories from the Voices that Matter attendees.

We’ll raffle off The Professional Ruby Collection: Mongrel, Rails Plugins, Rails Routing, Refactoring to REST, and Rubyisms CD.

GeeZeo offices
750 Main St, Hartford
Suite 1314
(next to the CVS)

Thanks to GeeZeo for hosting us, to Sun for feeding us, and to Addison Wesley for giving us books to raffle off. Hope to see you there!

Hartford Ruby Brigade next meeting: 10/27

The Hartford Ruby Group is meeting this Monday, 10/27, at 6:00 PM.

We’ll be tackling a Ruby Quiz problem, pairing up newcomers with veterans, and we’ll be raffling off a copy of Design Patterns in Ruby, by Russ Olsen.

GeeZeo offices
750 Main St, Hartford
Suite 1314
(next to the CVS)

Thanks to GeeZeo for hosting us, to Sun for feeding us, and to Addison Wesley for giving us books to raffle off.  Hope to see you there!

Hartford Ruby Brigade meeting tonight

If you’re in the area, feel free to drop in:

The Hartford Ruby Brigade’s September meeting is tonight, from 6 to 8 PM, at GeeZeo’s offices on 750 Main St, Suite 1314, in Hartford (next to the CVS).

The big news is Addison Wesley has a ticket for the Voices That Matter: Professional Ruby Conference this November, and we’ll raffle it off. It looks like a sweet conference, go take a look. You have to be there to win, so if you’ve been waiting for the right time to make an appearance, this is it. And since only one of us can win the ticket, we’ll also raffle off a great Ruby book, Hal Fulton’s The Ruby Way. A big thanks to Addison Wesley!

Aaron will give his long-promised IronRuby talk, and I’ll show a mini-project of mine that generates MSWord .docs from Textile, with RedCloth. It’s flashy, I promise.

Remember, if you have a topic you’d like to talk about, or one you’d like to hear about, or even if you just have an idea for what to do for the evening, don’t be shy, speak up! The group is what we make it, and it belongs to all of us.

As always, we’ll have free pizza and soda, courtesy of Sun Microsystems.

Hope to see you there!

Next Page »


Say Hello

danbernier [at] gmail [dot] com
Twitter @danbernier
Hartford.rb
LinkedIn

I’m a BackPack fan

Backpack

Categories