In order to explain the difference between functional and iterative
programming, I shall concentrate on how you specify a conditional
expression using different languages. My example is extremely
practical, and it deals with the way Planck/LFI radiometers are
labeled. LFI has 22 radiometers but only 11 antennas: the radiation
entering each antenna is split into two polarised components and each
of them enters a separate radiometer, called either ``main'' or
``side'' and labeled with M or S. To indicate a radiometer, one append
the number of the antenna to the string LFI, then it appends either
M or S, depending on the radiometer. So for instance the ``main''
radiometer fed by the twentieth antenna is LFI20M.
Of course, since it is much easier to deal with numbers than with
letters (e.g. to implement cycles), many codes used within the
Planck/LFI collaboration internally use 0 and 1 to represent the main
and side radiometers. A very common task is therefore to build the
name of the radiometer given two integer variables horn and rad
(the number of the antenna and of the radiometer, the latter being
either 0 or 1). Let's see how we can implement this in Python:
if rad == 0:
rad_letter = 'M'
else:
rad_letter = 'S'
name = "LFI%d%s" % (horn, rad_letter)
This is a rather naive approach employing the if conditional
statement. We can reduce the number of lines by throwing away the
else part:
rad_letter = 'M'
if rad == 1:
rad_letter = 'S'
name = "LFI%d%s" % (horn, rad_letter)
The best solution is however to forget about the if and use a
dictionary:
rad_letter = { 0: 'M', 1: 'S' }
name = "LFI%d%s" % (horn, rad_letter[rad])
This is the shorter solution, but likes the ones above it forces us to
define a new variable, rad_letter. It is not elegant if we are going
to use it in the following line only.
Other imperative languages do not allow many alternatives: they
usually require the very same code seen above. Here is e.g. the
solution in Pascal (another imperative language which does not support
dictionaries natively):
if rad = 0 then
rad_letter := 'M'
else
rad_letter := 'S';
name := 'LFI' + str(horn) + rad_letter
What offer functional languages in this context? Well, for any
functional language every statement is an expression and can be
therefore composed with other expressions. So the above example in
Scheme would be rewritten in this way:
(string-append "LFI" (number->string horn) (if (= rad 0) "M" "S"))
A very similar expression can be coded using Haskell:
"LFI" ++ (show horn) ++ (if rad == 0 then "M" else "S")
(the ++ function concatenates strings.) Note that in both cases we
do not need to define an ancillary variable: everything can be put in
one line.
Conceptually, the Scheme/Haskell solution would be the same as the
following pseudo-Python code:
name = 'LFI' + str(horn) + (if rad == 0: 'M' else 'S')
with the difference that this is not accepted by Python: it will
generate a ``bad syntax'' error. Note that GNU R has no problems in
accepting this construct:
name <- paste("LFI", horn, if(rad == 0) "M" else "S", sep = "")
(the paste command joins strings): this suggests that GNU R is more
functional than Python.
You might have noticed that I left C outside of this discussion. Well,
it turns out that C/C++ do not allow to include an if within an
expression, but it has a useful shorthand, the ``question-mark
operator'':
sprintf(name, "LFI%d%c", horn, rad == 0 ? 'M' : 'S');
The syntax of this operator is: cond ? iftrue : iffalse. Note
however that this is not really the if operator, but something else
that behaves exactly like it. (And it is a second-class operator, as
you cannot use it with C++ strings.) Moreover, the generalisation of
the if statement is the switch statement (where the decision is
not based on a true/false value, but on arbitrary values): and the
latter cannot be used in a C expression. On the other side, the
analogue of switch in Scheme (cond), Haskell (case) or OCaml
(match) can be used in expressions exactly like if.
This post has shown that even in simple cases functional constructs
can lead to shorter code. To see some striking example, be sure to
have a look at the site Bonsai code. Its author, Remco Niemeijer,
posts the shortest possible Haskell program which solves each
problem posted in Programming praxis. Sometimes I am astonished how
short the Haskell solution is!