If you’re a Java developer and start digging into some Java blogs, forums, books, etc. you’ll surely find some people arguing in favor of Scala, and read a lot of people talking about its functional approach and how cool it is.
Here I won’t attempt to cover Scala’s features in depth, though I will point out why I think it’s worth giving it a try.
Some history
Scala was designed in 2001 and its first version was implemented in 2003 on the Java platform, by Ph D. Martin Odersky. He is a professor of programming methods at EPFL, implemented Java generics and also the current generation of javac, so I am pretty sure this guy has a lot of Java Knowledge 🙂
Later, on January 2011, the Scala team won a five year research grant of over €2.3 million and with this funds, in May, Odersky and his collaborators founded Typesafe Inc. In 2012 Typesafe received a $3 million investment from Greylock Partners.
Though you may wonder, is this just a theoretical research from some university? or, Is it a platform to build enterprise software? Well, after looking at who’s using it, it turns out that many companies are building new services based on Scala, including Siemens, Novell, Sony, LinkedIn, Foursquare and Twitter.
Let’s get into some code
Syntactic sugar
As a newer language it provides some syntactic constructions aiming at the developer efficiency. Some quick examples:
val p = new Person // Type inference: no need for declaring variable’s type
p incrementAge 1 // Equivalent to p.incrementAge(1)
def deleteAll(dir: File = File.ROOT) = dir.delete // Method default parameters
object Person {
val MIN_AGE = 18
def adults(people: List[Person]) = people.filter(_.age >= MIN_AGE)
}
Scala aims at not disrupting object oriented principles, that’s why it has an object construction which is exactly what it says: one instance of a class. Provided that, and bearing in mind that you can name an object the same name as a class, there’s no more static keyword, just call an object by its name.
Functions
As you can read everywhere, Scala is an hybrid, it’s both an imperative object oriented language as well as a turing complete functional one. There’s a lot of interesting theory you can read about functional programming written by excellent authors, so here we’ll just see some examples again:
def filter[A](list: List[A])(predicate: A => Boolean) = …
A function taking another function as a parameter. predicate is a function that takes one element of the same type A of the list and returns whether it should be filtered or not.
def filterList = filter(List(“A”, “B”, “AB”, “BA”)) _
Here we’re creating another function utilizing the previous one but fixing one of its parameters, this returns a new function, which I called filterList. Note that it could have been declared as a val since in functional languages, functions are so called first-class citizens.
val startWithA = filterList(_ startsWith “A”)
Finally, we can call the filterList function with a predicate, which given an element of type String (inferred by the List of Strings) computes the standard java.lang.String.startsWith(String).
Pattern matching
Some people introduce pattern matching as a switch statement with some enhancements. In my opinion this is like an entire new feature since it’s more powerful and less restrictive.
Let’s see an example:
list match {
case List(“A”, “AB”) => “A -> AB”
case “ABC” => “A”
case Person(age, gender) => age + “|” + gender
case i: Int => “Int: ” + i
case s: String if s startsWith “A” => “Starts with A!”
case _ => “Default value”
}
Here we can see a lot of things going on. The first one is that we’re pattern matching on list value, and Scala will compare its value with the left side of each case expression, from top to bottom. In the first case we compare against a literal list, there we ask if it’s a list and if it contains those exact two strings. Then we simply compare to a string literal, or we can ask for the value’s type like the Int case. We can also add a conditional guard like the string with the if s startsWith “A” condition.
Everything is an expression
Another great thing to add is that the whole match we just saw is an expression and it’s returning the value on the right side of the matched case, meaning that we could write:
val myListString = list match { … }
And the compiler will infer the type of myListString, in this case being String, because all right sides are Strings. Though they could be of other types, and Scala would take the base class that all of them extend.
In fact, all sentences in Scala are expressions, meaning we can get the result, for example of an if expression:
val account =
if (user.registered) user.account
else defaultAccount
Traits
You can think of traits either as Java interfaces where you can implement methods, or as abstract classes with the advantage that you can extend as many as you want.
Whatever way you see it, traits are a pretty way of encapsulating behavior and reutilizing code.
Imagine you have a Bird class like this:
abstract class Bird {
def flyMessage: String
def fly() {
println(flyMessage)
}
def swim() {
println(“I’m swimming”)
}
}
Then you could use it like this:
class Pigeon extends Bird {
val flyMessage = “Flying like a Pigeon” // Yes, Pigeons can swim
}
class Hawk extends Bird {
val flyMessage = “Flying like a Hawk”
}
List(new Pigeon, new Hawk).foreach(_.fly())
That was easy. Now suppose you need a bird like the Penguin, who can swim but which can’t fly. Then you could make an abstraction like FlyingBird so Pigeon and Hawk would extend it while Penguin could directly extend Bird.
Ok, now there comes the Frigatebird, a bird that can fly but cannot swim. This bird will surely drive you crazy because he can’t swim and, in a language like Java, you can’t create a class hierarchy modeling all these birds, without duplicating code. The problem we are facing here is the well known problem of multiple inheritance and how Java handles it, you can create two abstract classes one for flying and another one for swimming, but you can’t extend both.
Here’s how you would likely solve it if you’re using Scala:
trait Bird
trait Swimming {
def swim() {
println(“I’m swimming”)
}
}
trait Flying {
def flyMessage: String
def fly() {
println(flyMessage)
}
}
This is how birds would look like:
class Penguin extends Bird with Swimming
class Pigeon extends Bird with Swimming with Flying {
val flyMessage = “Flying like a Pigeon”
}
class Frigatebird extends Bird with Flying {
val flyMessage = “Flying like a Frigatebird”
}
And now you could execute things like this:
List(new Pigeon, new Frigatebird).foreach(_.fly())
But something like this won’t compile:
List(new Frigatebird, new Penguin).foreach(_.fly())
In this last case, Scala would complain that fly is not a member of Bird. That’s because it infers that Bird is the only class that Frigatebird and Penguin have in common, assigning Bird as the type parameter of the List.
So, why Scala?
Besides these features we’ve quickly looked at, Scala introduces implicits, structural types, extractors, and many more, taking the best from both worlds (Object Oriented and Functional Programming). Having that said, it could be stated that Scala is concise, flexible and Scalable.
I haven’t mentioned performance, but you could be worried about some functional constructions that create new instances instead of writing values in-place. Well, we know that the garbage collector is usually pretty good with short-lived objects but also, thanks to the concise language, you can spend your time optimizing critical parts instead of dealing with tedious non-performance critical parts. There are a few benchmarks that compare Scala to Java and they confirm that it performs fast.
As I mentioned earlier, Scala is accepted by the industry, so you can be sure it will last long and its community will be supported.
Finally it’s good to know there are plenty of tools to empower Scala, from plugins for almost every IDE and a very cool building tool, to web frameworks and database access libraries.
In the worst case scenario you could end up writing Java-style code in Scala and it would be compiled to almost the same binary code and it’d be run in the same JVM. The question we should ask ourselves is: why don’t we just give Scala a try?
References
-
M. Odersky, L. Spoon and B. Venners – Programming in Scala Ed. artima Second edition. Dic 2010
- joelabrahamsson.com/learning-scala-part-seven-traits