A Postfunctional Language

By odersky

Created 2010-01-21, 23:12

The past couple of years have seen some extended debates on whether Scala is a functional language. On the one hand, Scala offers essentially all programming constructs typically associated with functional programming and a lot of Scala code is purely functional. On the other hand quite a few people disagree that Scala is a functional language. For instance, Robert Fischer writes that Scala is Not a Functional Programming Language[1] and Daniel Spiewak summarizes some of the arguments asking Is Scala Not Functional Enough?[2]

I'd like to argue that a good adjective for characterizing Scala is postfunctional: The essential parts of functional programming were all absorbed into Scala, even if some of the "look-and-feel" is different. Also, functional programming in Scala is just a (very important) part of a larger toolbox. I see Scala as one of the leaders in a larger trend where functional programming is being progressively absorbed into the mainstream. This movement is gaining momentum. For instance, every new version of C# seems to be more functional than its predecessor and even Java might finally acquire closures[3]. Of course, the addition of closures or type inference does not yet make a functional language, but it's the trend that counts here.

In arguing that Scala is postfunctional I should first clarify what I mean by a functional language. There are essentially two definitions in circulation, one narrow and one broad. The narrow definition is that a functional programming language should permit only pure functions and should not allow side effects. According to that definition, there are hardly any functional languages in use; even Haskell has the I/O monad and unsafePerformIO. So I prefer the broad definition: that a functional language makes programming centered around functions easy and natural. I think that's what Scala does, so by that reasoning it should count as a functional language.

To go into more detail, let's run down a list of features that are typically associated with functional languages.

Functions as first class values: check

Convenient closure syntax: check

List comprehensions: check. Scala's for expressions can express lists as well as other monads.

Narrowing the focus on statically typed functional languges, there are a few more points:

Powerful generics, including higher-kinded types: check

Type classes: check, they can be modelled by implicit parameters.

Type inference: half check. Scala has local type inference, which is useful but less powerful than the Hindley/Milner style of inference that's used in languages like Haskell, ML, and OCaml. On the other hand, local type inference plays nicer with subtyping.

Do people use it like a functional language? Sure they do. For instance, the Scala compiler sources and Scala libraries are written in a predominantly functional style. Map, filter, fold are ubiquitous. Pattern matching is used everywhere. There are very few mutable variables, and most of them are used in a single-assignment style.

So why do people disagree that Scala is functional? The two main reasons seem to be syntax choices and the role of OOP.

Scala feels less functional because its core syntax is largely in the tradition of Java, not Lisp, ML, or Haskell, the three most prominent ancestors of functional language families.

In particular, Scala does not have a different and generally awkward syntax for dereferencing mutable variables and for defining effectful computations. You might think that's bad, because it does not sufficiently discourage programmers from staying with their old imperative ways. That's a judgement call on what one wants to achieve with a language, which is completely valid to make. But in this blog post I'm only interested in characterizing what Scala is, not why it is what it is, or whether it should be something else.

Scala also deviates from some syntactic idioms that are considered typically functional. For instance, currying is more verbose and much less used than in other functional languages. Or, there are no algebraic data types, you have to write a sequence of case classes instead.

The other reason why Scala is sometimes discounted as a functional language is because it embraces object-oriented programming instead of rejecting it. Some functional programmers misunderstand OOP, and think for instance that OOP is inherently tied to mutable state (to be fair, many publications on OOP are reinforcing that belief). Scala is built on the hypothesis that one can be both functional and object-oriented, and that a lot is to be gained from this combination.

To summarize, if you look at the features Scala provides, it is substantially a functional language, but on the surface it does not always look like one, and it does not force you to adopt the functional style. For many of its users, the functional programming constructs in Scala are the most important set of tools it has to offer but they are not the only tools. In fact, great care has been spent in the Scala design to make functional constructs, imperative constructs, and objects all play well together. I think postfunctional is a good term for that blend.

An interesting comparison is with structured programming. In the 70s, structured programming was an important new programming style, and languages such a Pascal, Modula, or Ada were created to support this style better than others. Twenty years later you could have asked whether Java is a structured programming language? It has essentially all the features of these earlier languages, even though it looks different. It also does not have a goto statement. Does that make Java a structured language? Maybe. In reality it does not matter all that much anymore. Structured programming has "won'' to a degree where almost every language now follows its principles, even if the surface syntax is different. What's more, structured control is just one aspect among many others in programming languages today.

I hope that the same will happen to functional programming: that it will be absorbed into the mainstream until people stop thinking of functional programming as a different, novel, or exotic way to code, and use it instead as part of their daily routine. The same has happened with structured programming and object-oriented programming before. Functional programming could well be next, so that Scala would be an early example of a new breed of postfunctional languages.