The Promises of Functional Programming
Total Page:16
File Type:pdf, Size:1020Kb
S cieNTIFic P ROGRAMMING Editors: Konstantin Läufer, [email protected] Konrad Hinsen, [email protected] THE PROMISES OF FUNC T IONAL PROGRAMMING By Konrad Hinsen Adopting a functional programming style could make your programs more robust, more compact, and more easily parallelizable. However, mastering it requires some effort. ince the early days of com- (Alonzo Church’s λ-calculus) and as a probably Mathematica, although most puting, software development programming technique in the 1950s Mathematica users don’t write com- S techniques have changed (John McCarthy’s Lisp language)— plex functional programs. Another almost as much as computer tech- functional programming. Although example of symbolic processing is the nology itself. Ever more powerful functional programming has been widely used fast Fourier transform li- hardware made it possible to write very popular in computer science brar y, FF TW,1 which uses a function- ever more complex software, which research for several decades, its use al code optimizer written in OCaml both required ever better develop- for writing real-life programs is rela- to produce optimized C code for a ment tools and techniques and made tively recent. Of the many reasons Fourier transform of a given length. their implementation possible. Pro- for this, the two most important are In numerical applications, functional grammers thus moved from machine that functional programming is very programming doesn’t yet play an im- code to assembly languages and then different from traditional program- portant role. Perhaps the most ambi- problem-oriented programming lan- ming (also referred to as imperative tious project to introduce it into the guages, which have evolved to inte- programming) and thus requires a lot number-crunching world was Law- grate techniques such as structural of learning and unlearning, and that rence Livermore National Laborato- and object-oriented programming. computer hardware implements the ry’s Streams and Iteration in a Single Another evolution went from mono- imperative programming model, so Assignment Language (SISAL) proj- lithic programs via separately compil- imperative programs are easier to ect, which started in 1983. SISAL is a able modules and libraries to software compile into efficient machine code functional language with paralleliza- component technologies. However, in than functional programs. However, tion support, designed specifically for one respect, today’s popular program- several clear signs indicate a growing the needs of scientific applications. ming techniques are still the same as interest in functional programming Unfortunately, it didn’t attract the those the pioneers used: our programs techniques—recent programming attention it deserved, and funding consist of statements that modify data languages (such as Sun’s Fortress or stopped in 1996. Today, SISAL lives stored in the computer’s memory until Microsoft’s F#) have the explicit goal on as an open source project (http:// that memory contains the desired re- of supporting it. The reason is that sorceforge.net/projects/sisal). sult. This approach closely resembles functional programming has several This article’s purpose is to explain how a computer works at the hardware advantages for concurrent and par- what functional programming is and level: the processor fetches data from allel programming. Experience also how it differs from traditional impera- memory, performs elementary opera- suggests that functional programs are tive programming. I also explain how tions on it, and writes the result back more robust and easier to test than functional programming helps with to a memory cell. imperative ones. concurrent and parallel program- In fact, this approach is so com- In scientific computing, research- ming. The language I use in the ex- mon that most of you have probably ers have mainly used functional pro- amples is Clojure, a modern dialect never questioned it. And yet, an al- gramming for symbolic processing. In of Lisp (see the sidebar “Clojure and ternative approach was developed fact, the most widely used functional the Lisp Family”), but everything said as mathematical theory in the 1930s programming language in science is here applies equally to other function- 86 Copublished by the IEEE CS and the AIP 1521-9615/09/$25.00 © 2009 IEEE COMPUTING IN SC IEN C E & ENGINEERING CLOJURE AND THE LISP FAMILY he language used in the main text’s examples is Clojure, a modern dialect Tof the Lisp language family. Lisp stands for “list processing,” which hints at the motivations of John McCarthy, who developed the first Lisp language in the late 1950s for use in artificial intelligence research. Today, the most widely al languages, only the syntax will be used Lisp dialects are Scheme and Common Lisp. different. If you’re interested in func- The Lisp language family’s distinctive feature is the principle that “code is tional programming, you should also data.” Lisp provides a syntax for a simple yet flexible data structure—nested lists. read (or reread) Jerzy Karczmarczuk’s It then defines how to interpret nested lists that follow specific conventions as 1999 article in this magazine,2 which executable code. The advantage of expressing code in a data structure is that illustrates how functional program- Lisp code can easily generate (and then execute) other Lisp code, a fact that pro- ming can yield elegant solutions to grammers have exploited from the beginning through Lisp macros, the world’s problems in mathematical modeling. first meta-programming system and probably still its most powerful one. Lisp has the reputation of being slow, but that isn’t true anymore. Many The Basics modern compilers can produce code that can compete with C in performance The fundamental principle of func- when given appropriate optimization hints. However, it remains very difficult tional programming is that you re- to produce programs that are both efficient and portable between compilers alize a computation by composing and platforms. functions. The word “function” is Clojure is a recent Lisp dialect that sets itself apart by three features: it has used here in the mathematical sense— four highly optimized data structures (lists, vectors, maps, and sets) designed a mapping from input values to output for pure functional programming, it offers extensive support for concurrency, values—whereas what most program- and it was designed for the Java Virtual Machine with the goal of easy inter- ming languages call “functions” are operability with other JVM languages, including Java itself. For more informa- subroutines that return a value. One tion about Clojure, see its Web site at http://clojure.org. important difference is that a func- tion in the mathematical sense always produces the same output when given the same input. An operation such as write a useful program in a functional guage like Python and JavaScript). If n “get the next line from a file” isn’t a style, but keep reading. is zero, the return value of countdown function because each time you call, What replaces loops in functional is (list 0), a list containing the sin- it produces a different return value. programs is recursion. A function gle element 0. Otherwise (we’re look- Another important difference is that is called recursive if it calls itself— ing at lines four to six now), the return a mathematical function doesn’t “do” directly or indirectly. Of course, value is a list constructed by prepend- anything other than return a value. It calling itself makes sense only if the ing n to the return value of count- isn’t supposed to have side effects—for arguments change between calls. down for (- n 1), which is Clojure’s example, it shouldn’t write anything to Moreover, if you ever want to get out way of writing n-1. The function call a file or change a variable in memory. of the call-yourself chain, a recursive (countdown 1) thus returns (cons If a program is composed of func- function must return without calling 1 (countdown 0)), which, after ex- tions, and functions aren’t supposed itself for some arguments. Let’s look ecuting the recursive function call, to change any variables, then what are at a simple example of recursion: becomes (cons 1 (list 0)). Look- variables good for? Nothing, and that’s ing up the definitions of the functions why functional programming doesn’t (defn countdown [n] cons and list will tell you that the have variables. This is probably the (if (zero? n) final result is the two-element list (1 biggest surprise to those who discover (list 0) 0). This simple example illustrates functional programming because vari- (cons n how to use recursion for looping: with ables are so very fundamental to our (countdown each recursive call, the argument be- traditional ways of writing programs. (- n 1))))) comes smaller, up to the point where The other missing fundamental con- it’s handled directly without any fur- cept is loops. After all, what’s the point These six lines define a function ther recursion. of a loop if nothing can change be- countdown of a single argument n, A closer look at the chain of recur- tween iterations because there are no which should be an integer (although sive calls to countdown also reveals variables? By now, you might be con- this is neither said nor enforced, Clo- why functional programming can live vinced that it’s absolutely impossible to jure being a dynamicallly typed lan- without variables. At each recursive JULY/AUGU S T 2009 87 S cieNTIFic P ROGRAMMING call, n decreases by one, which looks a to the programmer. As is so often the are called higher-order functions, as op- bit as if n were a variable decremented case, both approaches have their good posed to first-order functions whose from its initial value to zero; indeed, and bad sides.