The Scala Way

A colleague who recently began learning Scala indicated that the most challenging aspect was figuring out how to do things the Scala way. Having worked with many programming languages, he easily accomplished the more mundane language learning tasks related to syntax, package structure, class hierarchy, etc. However, leveraging the rich features of Scala’s functional-object-oriented hybrid programming model was proving elusive. Recalling my own experiences learning Scala, I remembered facing the same challenge. While there are numerous sources of Scala documentation, in particular Martin Odersky’s Programming in Scala is a fantastic overview of the language, there seems to be little that addresses how a programmer, experienced or novice, should approach the task of learning how to adopt the Scala idioms. I attempt to address that here by suggesting four areas to focus on when first learning the Scala way. 

avoid State

Much of what one might call “the Scala way” is really just the functional way. While there are many functional programming languages, each with their own unique features, they tend to share a common functional programming style that is quite different from the more familiar object oriented programming (OOP) style. Perhaps of greatest import is that state is abhorred. Though state cannot be eliminated entirely in most programs, much of it can be avoided. In Scala, the primary way to recognize that you are developing in a stateless manner is that your variables are immutable, i.e. are marked with the Scala val keyword rather than the var keyword. If you come from an OOP background, the exclusive use of immutable variables may sound impossible. Rest assured, adopting the ideas that follow in the rest of this article, will resolve most of the associated challenges.

for No More

If you do only one thing to adopt the Scala way, make it forgoing the use of for loops. In Scala, a for loop can always be replaced with List methods. There are at least two very good reasons for doing so. First, your code will almost certainly be more concise and more readable. Secondly, adopting these methods will tend to force you to use many other functional techniques. Consider the following example definition of a function that computes the distance between two vectors:

The Non-Scala Way:

def distance(v1 : Array[Double], v2: Array[Double])  = {
        var sumsquare = 0;
        for( i <- 0 to (v1.length-1)) {
            sumsquare += (v1(i) -v2(i)) * (v1(i) – v2(i))
        }
        math.sqrt(sumsquare)
}

The Scala Way:

def distance(v1 : Array[Double], v2: Array[Double])  = {
        Math.sqrt((0.0 /: v1.toList.zip(v2)) ((sum,t) => sum + (t._2-t._1)*(t._2-t._1)))
}

Yes, one line of code in the Scala way and immutable variables only. The key, fancy List methods like zip and /: (foldLeft). There are many other List methods and they are worth exploring in depth as you learn Scala. 

switch To match

One of Scala’s most powerful features is pattern matching. If you have prior programming experience, you can think of the match statement as a switch statement on steroids. In adopting the Scala way, you will mostly avoid if statements, particularly those with multiple else if clauses, as a primary control flow mechanism. Indeed, in most of my Scala code I only use if in assignment statements as in:  val x = if (condition) value_1 else value_2. Unlike say the Java switch statement which only allows comparisons of integer values, the Scala match statement allows comparisons on just about any object type. As such, it can be used very effectively as a logic flow control statement. For example, error checking can be added to the previous distance method as follows:

def distance(v1 : Array[Double], v2: Array[Double])  = {
        v1.toList match{
               case Nil => throw new Exception(“Empty Array”)
               case l1 => v2.toList match{
                   case Nil => throw new Exception(“Empty Array”)
                   case l2 => if(l1.length==l2.length)
                                  Math.sqrt((0.0 /: l1.zip(l2)) ((sum,t) => sum + (t._2-t._1)*(t._2-t._1)))
                                     else throw new Exception(“Unequal Length Arrays”)
             }
       }
}

f(g(x)), functions As Parameters

Like most functional languages, methods are first class objects in Scala. As such, the Scala way often involves passing a method as a parameter into another method. Used appropriately, this technique will contribute to reducing state in your applications and making your code more efficient. Building on the distance method example, consider a method that computes the magnitude of the sum of two vectors. One could simply write an additional method for this new computation. However, the Scala way involves using a single method that operates on the two vectors generically and accepts a function as a parameter for the actual computation. This makes the control flow code in the generic method reusable for any number of computations:

def generic(v1 : Array[Double], v2: Array[Double],
        f:(Double,   Tuple2[Double,Double])=>Double, start:Double) = {
        (start /: v1.toList.zip(v2)) ((v,t) => f(v,t))
}

def distnce(v1 : Array[Double], v2: Array[Double]) = {
        Math.sqrt(generic(v1,v2, (sum:Double,t:Tuple2[Double,Double])=>
                                                                     sum +(t._2-t._1)*(t._2-t._1), 0.0))
}

def magnitudeSum(v1 : Array[Double], v2: Array[Double]) = {
        Math.sqrt(generic(v1,v2, (sum:Double,t:Tuple2[Double,Double])=>
                                                                     sum +(t._2+t._1)*(t._2+t._1), 0.0))
}

next Steps

Hopefully, this has provided you with an outline for learning the Scala way. Where you go from here is largely dependent on what you need to do with your development projects. Some of the features that I have found useful include currying, traits, and companion objects. Happy coding.

About these ads
This entry was posted in Tutorial and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s