This site will look much better in a browser that supports web standards, but is accessible to any browser or Internet device.

Anomaly ~ G. Wade Johnson Anomaly Home G. Wade Home

January 25, 2009

The Literals of Functional Programming

I was listening to an older episode of Software Engineering Radio where they interviewed Martin Odersky on Scala (Episode 62). In the interview, Odersky made a comment about closures being the literals of functional programming. This statement struck me as surprising. The more I thought about it, the more interesting and subtle the concept became.

In functional programming, functions are first-class values. (OOP advocates often say first-class objects, but this concept is more fundamental than that.) If a function is a value, like an integer is a value, a closure (or anonymous function) is the equivalent of a literal (like 2). This idea has been wandering around in my head for the last few days. The more I think about it, the more interesting it appears.

To get the most that you can out of an analogy, you need to apply what you know from one side of the analogy to the other to see if it gives any insight. Let's start with what we know about literals:

Magic Literals

We all know the problems with magic literals. Leaving them scattered around the code is a guaranteed way to make unmaintainable code. If the same magic literal is used in multiple spots, then making changes is harder than it needs to be. We normally solve this problem by replacing the literal with a defined constant. If that constant is well-named, this improves the readability of the code. (If the constant is not well-named, it can actually make things worse.)

There are a few cases where we may decide to use a literal despite this fact.

The initial index for a loop is almost always 0 (for C, C++, Perl, Java, etc.). There's really no need to name this literal, because it's function is obvious and it will not change (for a given language). Just as importantly, it's hard to come up with a name that means more to us that the value of the constant itself (please don't name it ZERO).

If you are working with date manipulation code, the literals 7 and 12 are obvious enough that we might not choose to make the constants DAYS_PER_WEEK or MONTHS_PER_YEAR. This decision is not quite as obvious, but it would be relatively easy to justify not making a constant. On the other hand, most people would probably prefer MINUTES_PER_DAY to 1440 and SECONDS_PER_DAY to 86400. This shows that if the use of the literal is obvious enough, we may not need to name it. If there's any question about the purpose of the constant, we give it a name.

Another possibility would involve implementing an algorithm from a book that contained a large number of single use magic literals. You would probably keep the literals and reference the original algorithm in a comment rather than add constants that weren't in the original algorithm. In this case, being faithful to the original algorithm trumps concerns over magic literals.

Function Literals

The first thing that is worth considering about anonymous functions from this analogy is the possibility that giving the function a name might be wise. If the function is used in many places, giving it a name is probably good for maintenance. (Just like making a constant out of a numeric literal simplifies maintenance.) Likewise, code containing a large number of anonymous functions is likely to be hard to maintain.

Also like the magic literal issue, there may be cases where the anonymous function is obvious enough that no name is needed. I'm going to propose some examples using the Perl programming language for the syntax. This is mostly because Perl has a fairly reasonable syntax for anonymous functions. It also has three operators for manipulating lists that make use of anonymous functions: map, grep, and sort, Let's use map. (The map operator generates a new list by applying an anonymous function to all of the elements of another list.)


@newlist = map { $_*2 } @oldlist;

Once you know that $_ is the argument to the subroutine, it is obvious that this anonymous function doubles its argument. In this context, @newlist is a list where all of the elements are the doubles of the elements of @oldlist. A similarly obvious example (with better named variables) would be:


@elapsed_secs = map { $_*60 } @elapsed_minutes;

This anonymous function converts minutes to seconds by multiplying by 60. Giving the function a name would not really clarify things any. What about


@newlist = map { $_*($_*17 + 33) + 42 } @oldlist;

This example is the equivalent of a magic literal in the code. I can't imagine anyone looking at this and deciding that it is perfectly clear. Much like code containing the magic literal 17, this function should be named. Otherwise, the code is hard to read and maintain.

Filtering with Predicates

Another place that anonymous functions are useful is when filtering a list using grep. Like the map cases above, we can see that simple tests make good function literals.


@positive = grep { $_ > 0 } @unfiltered;

This anonymous function obviously selects positive numbers. Just like the next one selects numbers below a cutoff.


@selected = grep { $_ < $cutoff } @unfiltered.

However, just like the map, we can have examples that would benefit from naming the function.


@filtered = grep { $_ > 3 && $_ < 13 && $_%2 == 0 } @unfiltered;

It's going to be practically impossible to understand this without some help, so turning this anonymous function into a named function is probably worthwhile.

Further Consideration

Like numeric literals, functional literals can make code harder to understand. However, giving all closures names as a knee-jerk reaction is not a valid answer. Consider naming anonymous functions when it would make the code clearer without breaking it. I'm still not sure whether anonymous functions are as bad for maintenance as numeric literals. More thought and experimentation is needed.

So far, I don't feel like I've made it through very many of the implications of anonymous functions being the functional programming equivalent of literals. I'll probably write more later, as more implications come to me.

Posted by GWade at January 25, 2009 08:30 PM. Email comments