This content is part of the series:Charming Python

Stay tuned for additional content in this series.

In Part
1, my previous column on functional programming, I introduced some
basic concepts of FP. This column will delve a little bit deeper into this
quite rich conceptual realm. For much of our delving, Bryn Keller's
"Xoltar Toolkit" will provide valuable assistance. Keller has collected
many of the strengths of FP into a nice little module containing pure
Python implementations of the techniques. In addition to the module
functional, Xoltar Toolkit includes
the lazy module, which supports
structures that evaluate "only when needed." Many traditionally functional
languages also have lazy evaluation, so between these components, the
Xoltar Toolkit lets you do much of what you might find in a functional
language like Haskell.

Bindings

Alert readers will remember a limitation that I
pointed out in the functional techniques described in Part
1. Specifically, nothing in Python prevents the rebinding of names
that are used to denote functional expressions. In FP, names are generally
understood to be abbreviations of longer expressions, but the promise is
implicit that "the same expression will always evaluate to the same
result." If denotational names get rebound, the promise is broken. For
example, let's say that we define some shorthand expressions that we'd
like to use in our functional program, such as:

Listing 1. Python FP session with rebinding causing mischief

Unfortunately, the very same expression
sum2(range(10)) evaluates to two different
things at two points in our program, even though this expression itself
does not use any mutable variables in its arguments.

The module
functional, fortunately, provides a
class called Bindings (proposed to Keller by
yours truly) that prevents such rebindings (at least accidentally, Python
does not try to prevent a determined programmer who wants to break
things). While use of Bindings requires a
little extra syntax, it makes it difficult for accidents to happen. In his
examples within the functional module,
Keller names a Bindings instance
let (I presume after the
let keyword in ML-family languages). For
example, we might do:

Obviously, a real program would have to do something about catching these
"BindingError"s, but the fact they are raised avoids a class of problems.

Along with Bindings,
functional provides a
namespace function to pull off a namespace
(really, a dictionary) from a Bindings
instance. This comes in handy if you want to compute an expression within
a (immutable) namespace defined in a Bindings.
The Python function eval() allows evaluation
within a namespace. An example should clarify:

Closures

One very
interesting concept in FP is a closure. In fact, closures are
sufficiently interesting to many developers that even generally
non-functional languages like Perl and Ruby include closures as a feature.
Moreover, Python 2.1 currently appears destined to add lexical scoping,
which will provide most of the capabilities of closures.

So what
is a closure, anyway? Steve Majewski has recently provided a
nice characterization of the concept on the Python newsgroup:

That
is, a closure is something like FP's Jekyll to OOP's Hyde (or perhaps the
roles are the other way around). A closure, like an object instance, is a
way of carrying around a bundle of data and functionality, wrapped up
together.

Let's step back just a bit to see what problem both
objects and closures solve, and also to see how the problem can be solved
without either. The result returned by a function is usually determined by
the context used in its calculation. The most common -- and perhaps the
most obvious -- way of specifying this context is to pass some arguments
to the function that tell it what values it should operate on. But
sometimes also, there is a natural distinction between "background" and
"foreground" arguments -- between what the function is doing this
particular time, and the way the function is "configured" for multiple
potential calls.

There are a number of ways to handle background,
while focussing on foreground. One way is to simply "bite the bullet" and,
at every invocation, pass every argument a function needs. This often
amounts to passing a number of values (or a structure with multiple slots)
up and down a call chain, on the possibility the values will be needed
somewhere in the chain. A trivial example might look like:

Listing 5. Python session showing global variable

The global N is simply available whenever you
want to call addN(), but there is no need to
pass the global background "context" explicitly. A somewhat more Pythonic
technique is to "freeze" a variable into a function using a default
argument at definition time:

Listing 6. Python session showing frozen variable

Our frozen variable is essentially a closure. Some data is "attached" to
the addN() function. For a complete closure,
all the data present when addN() was defined
would be available at invocation. However, in this example (and many more
robust ones), it is simple to make enough available with default
arguments. Variables that are never used by
addN() thereby make no difference to its
calculation.

Let's look next at an OOP approach to a slightly more
realistic problem. The time of year has prompted my thoughts about those
"interview" style tax programs that collect various bits of data -- not
necessarily in a particular order -- then eventually use them all for a
calculation. Let's create a simplistic version of this:

In our TaxCalc class (or rather, in its
instance), we can collect some data -- in whatever order we like -- and
once we have all the elements needed, we can call a method of this object
to perform a calculation on the bundle of data. Everything stays together
within the instance, and further, a different instance can carry a
different bundle of data. The possibility of creating multiple instances,
differing only their data is something that was not possible in the
"global variable" or "frozen variable" approaches. The "cargo" approach
can handle this, but for the expanded example, we can see it might become
necessary to start passing around numerous values. While we are here, it
is interesting to note how a message-passing OOP style might approach this
(Smalltalk or Self are similar to this, and so are several OOP xBase
variants I have used):

Each closure function we have defined takes any values defined within the
function scope, and binds those values into the global scope of the
function object. However, what appears as the function's global scope is
not necessarily the same as the true module global scope, nor identical to
a different closure's "global" scope. The closure simply "carries the
data" with it.

In our example, we utilize a few particular
functions to put specific bindings within a closure's scope (income,
deduct, rate). It would be simple enough to modify the design to put any
arbitrary binding into scope. We also -- just for the fun of it -- use two
slightly different functional styles in the example. The first
successively binds additional values into closure scope; by allowing
taxFP to be mutable, these "add to closure"
lines can appear in any order. However, if we were to use immutable names
like tax_with_Income, we would have to arrange
the binding lines in a specific order, and pass the earlier bindings to
the next ones. In any case, once everything necessary is bound into
closure scope, we can call the "seeded" function.

The second style
looks a bit more like Lisp, to my eyes (the parentheses mostly). Beyond
the aesthetic, two interesting things happen in the second style. The
first is that name binding is avoided altogether. This second style is a
single expression, with no statements used (see Part
1 for a discussion of why this matters).

The other
interesting thing about the "Lisp-style" use of the closures is how much
it resembles the "Smalltalk-style" message-passing methods given above.
Both essentially accumulate values along the way to calling the
taxdue() function/method (both will raise
errors in these crude versions if the right data is not available). The
"Smalltalk-style" passes an object between each step, while the
"Lisp-style" passes a continuation. But deep down, functional and
object-oriented programming amount to much the same thing.

Tail recursion

In this
installment, we have knocked off a bit more of the domain of functional
programming. What remains is less (and provably simpler?) than before (the
title of the section is a minor joke; unfortunately, its concept is not
explained herein). Reading the
functional module's source is an
excellent way to continue exploring a number of FP concepts. The module is
very well commented, and provides examples for most of its
functions/classes. Not covered in this column are a number of simplifying
meta-functions that make the combinations and interaction of other
functions simpler to handle. These are definitely worth examining for a
Python programmer seeking to continue the exploration of functional
paradigms.

Downloadable resources

Related topics

Bryn Keller's "xoltar toolkit", which includes the module
functional, adds a large number of useful
FP extensions to Python. Since the
functional module is itself written
entirely in Python, what it does was already possible in Python
itself. But Keller has figured out a very nicely integrated set of
extensions, with a lot of power in compact definitions.

Peter Norvig has written an interesting article, Python for Lisp Programmers. While his focus is somewhat the reverse of my column, it
provides very good general comparisons between Python and Lisp.

I've found it much easier to get a grasp of functional programming in
the language Haskell than in
Lisp/Scheme (even though the latter is probably more widely used, if
only in Emacs). Other Python programmers might similarly have an
easier time without quite so many parentheses and prefix (Polish)
operators.