Being a professional programmer since two decades (and being a programmer since three - wow!) I've learned a lot of languages. I've started when I was a child with Logo, then moved to BASIC. After that it came Pascal and later Modula-2. I've learner Tcl on Solaris, then discovered Perl and forgot everything else for a long while. I've done some Javascript on the web and some Java programming on the Android platform too. I've coded a lot in C (especially tagsistant and magma) and I've done some Joomla development in PHP.

Each of those languages has its particularities, that's for true. Perl and Tcl are interpreted dynamic languages for fast and furious programming, while Java is bloated enough to fulfill the requirements of enterprise class bureaucracy. C is the boss in the downtown of the hardware with its slim'n'lean functions and PHP has the right mix of functions, classes and chaos to cook a web page with perfectly burnt corners.

But all of them are imperative, or at least are usually used in the imperative way. And then enters Scala!

 

Scala is something really different, like introducing heavy metal in a gregorian choir. Scala offers an explosive mix of object oriented programming and functional programming. While a lot of the languages I've used offer support for OOP (Java, JavaScript, Perl, PHP and even C - yes!), none of them support functional programming. I was unaware of the ineffable elegance of FP until I've been exposed to Scala (because none of the historical FP languages ever entered my daily experience). In FP functions are treated the same way data are.

While in every language you can declare and return data, only FP languages allow functions to be declared and returned. In Scala is actually possible to pass a function as the argument of a function (like done with callbacks in C) but also to declare it inside a function and return it! That really makes the difference.

This line declares a function called seedCooker which accepts one integer argument called seed and returns a brand new function which in turns accept another integer argument called i and returns the argument i modulo the seed passed to seedCooker() in the first place:

def seedCooker(seed: Int) = (i: Int) => { i % seed }

Let's see it closer, it's easier than it seems. The first part is:

def seedCooker(seed: int) ...

def is a Scala keyword used to declare functions. seedCooker is the name of the function being declared, while seed is the name of its unique argument. The type of seed is declared right after it, following the colon.

Now the second part:

 ... = (i: Int) => { ... }

The = sign says: here follows the declaration of seedCooker(). Whatever follows is the value of seedCooker(). By value I don't mean a final, defined value like 5 or "Hello, world". I mean the essence of seedCooker(). And being seedCooker() a function, its essence must be a body, a segment of code which can be executed whenever seedCooker() is invoked. That body is:

(i: Int) => { i % seed }

Now, the next key concept to grasp to understand the whole thing is the pattern:

(...) => { ... }

The => operator is used to declare an anonymous function. What's an anonymous function? Simple: just a function without a name. But what is worth a function if it does not have a name? How it's supposed to be called if it does not have a name?

You may think to have a point, here, but in fact you don't. The anonymous function is what's returned by seedCooker() and it will be saved in an external variable, like in:

val sc10 = seedCooker(10)

Here seedCooker() has been called with a seed of 10, so it has returned a function which takes one Integer and return its modulo 10. The calling line assigned that anonymous function to the variable sc10, so we can now call that function with:

val mod32 = sc10(32)

Now, going back to our declaration, we could have obtained the same result with this code:

def sc10(i: Int) = { i % 10 }
val mod32 = sc10(32)

But what if the algorithm included in sc10 were not as simple as i % 10? We should have declared a different function scNNN for every seed NNN, duplicating the code of the algorithm. With the functional approach the algorithm is declared only once, inside seedCooker(), and initialized with a different seed at each call of seedCooker().

The algorithm could have been broken into several sub-functions which could have been declare inside seedCooker() without polluting the external namespace. A famous example is the factorial of a number which can be declared as:

def factorial(i: Int) = {
  def fact(i: Int): Int = { if (i == 1) then 1 else i * fact(i - 1) }
  fact(i)
}

val f5 = factorial(5)
f5: Int = 120

Now let's say that we want a modified version of the factorial algorithm which stops before reaching 1. Our threashold must be declarable like the seed of seedCooker(). We can change our code as:

def factorialCooker(seed: Int) = (i: Int) => {
  def fact(i: Int): Int = {
    if (i < seed) 0
    else if (i == seed) i
    else i * fact(i - 1)
  }
  
  fact(i)
}

val factorial = factorialCooker(3)

This new factorial function returned by factorialCooker(3) resembles the previous one with two particularities:

  1. for numbers greater or equal to 3, it returns the factorial of the number up to 3, since we initialized it to stop at 3
  2. for numbers smaller than 3, it returns 0

It's quite easy to test this with the Scala REPL, the interactive shell that allows the impatient programmer to test its Scala understanding:

$ scala
Welcome to Scala version 2.9.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_31).
Type in expressions to have them evaluated.
Type :help for more information.

scala> def factorialCooker(seed: Int) = (i: Int) => {
     |   def fact(i: Int): Int = {
     |     if (i < seed) 0
     |     else if (i == seed) i
     |     else i * fact(i - 1)
     |   }
     |   
     |   fact(i)
     | }
factorialCooker: (seed: Int)Int => Int

scala> val factorial3 = factorialCooker(3)
factorial3: Int => Int = 

scala> factorial3(3)
res1: Int = 3

scala> factorial3(2)
res2: Int = 0

scala> factorial3(1)
res3: Int = 0

scala> 

To declare another instance of the factorial function with a threshold of 6, we just call another time factorialCooker as:

scala> val factorial6 = factorialCooker(6)
factorial6: Int => Int = 

scala> factorial6(7)
res4: Int = 42

scala> factorial3(4) + factorial6(8)
res5: Int = 348

And 348 is precisely 4 * 3 + 8 * 7 * 6 = 12 + 336 = 348

Scala is a powerful language which blends OOP and FP in a way that will make you wonder why you ever used another language in your life. Many posts will follow this one while I expand my knowledge of Scala and its vast ecosystem, including the Play framework and Apache Spark.


  The Cog In The Machine On Which All Depends