A resurgence of functional programming outside of academia has been in the air for a couple years now, and I’ve finally decided to hop on the bandwagon. Since my current work involves lots of Hadoop programming in Java, I decided to go with Scala, the new new thing whose particular niche is as a mixed-paradigm, strongly-typed, object-oriented, functional programming language that compiles for the JVM. (For what it’s worth, I prefer Programming in Scala to O’Reilly’s Programming Scala.) Mostly I made the leap because I wanted to see what functional programming was all about. I hadn’t realized how much of this style was already familiar to me. Not just from sources that I would expect like Matlab and R but also from Ruby, which in other ways is as different from Scala as you can get. I thought what was distinctive about the Ruby idiom of chaining together
Enumerable objects was the way it made iterators first-class elements of the syntax, but arguably what is really going on here is a functional style of programming, since the anonymous function blocks that glue these objects together are all without side effects. Anytime in Ruby you elect to use the
inject method rather than accumulating a value in a variable, you’re being functional. It also turns out I’ve been speaking in prose my whole life. Who knew?
For me, the most interesting conceptual difference between imperative and functional languages is the atemporal character of the latter. Since objects are stateless and variables are immutable there is a sense in which a program is not a thing that changes over time. The cooking metaphor–where the program is a recipe and the computer is a chef–goes out the window. In its place is a description metaphor. The program is a description of a state of affairs to which the input either does or does not conform. In this sense it is more like a statement of pure mathematics. The program doesn’t run. It just is.
Of course it’s easy to overstate this. On some level the program has to run; otherwise the only appropriate platform for a functional language would be a computer that wasn’t plugged in. As with all programming languages, it comes down to metaphors and the emphasis of different parts of metaphors. Scala, for instance, is mixed-paradigm and so is not religious about atemporality. The most purely functional programing I’ve ever done was in writing Head-Driven Phrase Structure grammars. HPSG is a theory of natural language syntax with a computer implementation. You use its concepts to write a grammar of English, Japanese, Farsi, or what-have-you in a domain-specific language with constructions for describing verbs, nouns, intransitives, passive voice, modifier order, and the like. The resulting formalism looks not unlike what is pictured here. There are no control structures, just descriptions of words and patterns of words–essentially a linguist-friendly front-end for a big hairy regular expression. You “run” an HPSG program by handing this blob and a sentence over to a parser which then proceeds to give a thumbs up to, say, “The cat is on the table” while borking on “Cat the are is table on”.
Linguistics actually has some deep connections to functional programming, since a pure functional computer program is basically a set of truth conditions, and the notion of truth conditions–passed down from Frege via Montague–lies at the heart of mainstream formal semantics. Inasmuch as they are just an application of set theory, truth conditions are atemporal. (Of course you can discuss the truth conditions of changing situations, but then time is just another thing being described, and not part of your metalanguage.) Relative to some circumstance the sentence “The cat is on the table” is either true or not–it doesn’t gradually become true as we parse the sentence or apprehend the situation any more than the mathematical statement x =5 becomes true as we go through a series of algebraic steps to derive it from the statement x2+3x+9 = 49. The value of x was always 5 whether we knew it or not.
If you’ve done mathematical work for a while this is a natural way of thinking. Atemporality is part of the non-a posteriori nature of mathematical truth and makes things simpler because without time involved there’s one less thing to worry about. There’s no danger your proofs are going to get fouled up by a race condition. But there’s something in the portentous tone of “The value of x was always 5″ that feels like a bluff. What exactly does “always” mean, and do we admit some notion of temporality just by using the word? These philosophical conundrums don’t come up in the programming world because there’s always a human user standing outside the system. For them, in the end, functional programs do indeed run. At some point a compiler converts them to a series of CPU instructions which cause a particular blob of silicon to change its physical state in a particular way over time. There are side effects. Life is a side effect. Without this sense of dynamism, the content of truth conditions, or mathematics, or maybe even analytic truths in general seems in danger of being whittled away to nothing. Presumably the programming analogy breaks down before this becomes a problem–or at least maps to some familiar is-math-invented-or-discovered conundrum–but I’m having a hard time seeing how.