Saturday, April 20, 2013

Is Scala a Functional Language?

A few years ago, a guy called Robert Fischer wrote a blog post arguing that Scala is not a functional language.  What I found particularly interesting about it is that he claims to have worked a fair amount with Scala, but he doesn't exactly show a deep familiarity with the language.  Indeed, I've been programming with Scala for less than a year now, and I can say pretty confidently that I know it more thoroughly than he does.

So, is Scala a functional language?  I would say no.  Scala is a multi-paradigm language designed to blend functional programming with object-oriented programming.  I wonder who Robert thinks claims that it is a functional language, as most users would probably give the answer I just gave.  For example:

“Scala goes further than all other well-known languages in fusing object-oriented and functional programming.”
-- Martin Odersky

The language is designed to optimize the union between the two paradigms, rather than optimizing the use of either one separately.  However, I will also make the following claim: under the definition that Robert himself gives, Scala actually is a functional language. Let me use his examples for the purpose of demonstrating this.  According to his definition, a functional language is one which makes functional programming easy.

Let's start with the first example: Robert's claim is that the following is the easiest way to define a function:

object SomeHolderObject {
  val f(x:int):int = { x + 1 }
}
 
Bzzt, wrong.  I have no idea what compiler Robert's using, but the following runs just fine on the official compiler provided by type-safe (if you save it in a .scala file):

def f(x:Int) = x + 1

What this does, actually, is that it treats the program as a script, not an object.  This is one of the things that first attracted me to Scala, actually.  Before getting into Scala, I was a Python programmer (I still am, but I'm beginning to like Scala more and more).  The combination of type inference and ability to treat programs as scripts felt much like using a scripting language; I felt at home when using Scala.

Now, in a last-ditch attempt to save this example, one might argue that Scala requires that you specify the return type of the parameter of the function.  This is true, but it has nothing to do with making functional programming easy; it has to do with the type inference of the system.  Next.


def x(a:Int, b:Int) = a + b 
def y = Function.curried(x _)(1)
y(2)  // 3


I'm not normally one to assume my interlocutor is being dishonest, but I can't draw any other conclusion if I accept that Robert has worked "a fair amount" with the language.  Currying is actually much easier than that:

def x(a:Int)(b:Int) = a + b 
def y = x(1)_
y(2)  // 3

There's another way to do it without the syntactic sugar, which is less elegant but places more emphasis on the fact that functions are first-class values:

def x(a:Int) = {b:Int => a+b} 
def y = x(1)
y(2)  // 3

Actually, I have some reservations about the way OCaml does it, because that way, it's possible (easy?) to accidentally put the wrong number of parameters in your function.  With OCaml's syntax, instead of catching this error, the compiler will return a partially-applied function.  Also, SML is also not curried by default

Robert's final example involves algebraic data types.  Again, Scala's syntax is optimized to blend object-oriented and functional programming, rather than to use either one separately, and its implementation of case classes and pattern matching is a case in point.  Actually, one can create a similar syntax to OCaml's by using type aliases, but I'll just give this one to him.  Scala still wins 2 to 1, using his own examples.  Facepalm.

Overall, it seems that the author is either learning just barely enough Scala to write some truly horrendous code, or else purposefully writing the worst possible code in Scala and the cleanest possible code in OCaml just to give the latter the edge.

Actually, in a Stack Overflow topic on the subject, one of the commenters described as a "litmus test" for a functional language the Church numerals.  Church numerals are a way of encoding integers with the number of times a function is applied.  Well:

def thrice[T](f:T => T) = f andThen f andThen f
thrice[Int](1+)(0) // 3
thrice(thrice[Int](1+))(0) // 9
thrice(thrice[Int])(1+)(0) // 27

exactly as the commenter described it.  Another clear win for Scala, I'd say.

~Ian

No comments:

Post a Comment

Anything which is both a known logical fallacy and a personal insult will be mercilessly mocked all the way to fictional hell, and anything which is one or the other will be relentlessly rebuked. I am an unconditional proponent of free speech, and as such open debate is always welcome. This means that disemvowelling and temporary suspension will only be used when commenters have shown that they are nothing more than flamers. Commenters will only be banned completely when they post information that can actively harm another individual, such as docs. Anonymous comments are disallowed to weed out cowardly flamers who hide behind anonymity. If you play nice, this may change in the future :-)