Why I like Scala

Page content

I am familiar (more or less) with a number of programming languages and have both emotional and rational thoughts of them. Scala is for certain in the group of languages I like. I have decided to summarize my judgments of Scala attractive parts in a blog post and here it is. Also, I have got some ideas of posts about Scala and its technology stack and an introduction is possibly needed.

Scala logo

Scala is a general purpose programming language created by Martin Odersky more than ten years ago. It compiles into JVM byte code and interoperable (both direction) with Java (including mixed compilation), which gives Scala an ability to use all this enormous amount of code created for JVM. The interesting property and also one of the strongest selling points of the language is fusion of object-oriented and functional programming paradigms.

Some people think that Scala is an academic language, but they are totally mistaken. Scala is commercially supported (by Typesafe Inc.) and is used by many organizations including Twitter, Foursquare and LinkedIn.

Type system

What is good about Scala? The first thing I want to mention is a type system. Scala is statically typed, has a powerful type system (supports variance, different kind of type bounds, types of higher kind, structural types etc.) and infers types for you. This means something like “you can write clean and expressive code like in your-favorite-dynamic-language and never get AttributeError at runtime” :)

Type inference is very convenient: you almost never need to write types on variables and values:

def aMethod(): HashMap[Int, List[User]] = ...

val withTypeInference = aMethod()
val withoutTypeInference: HashMap[Int, List[User]] = aMethod()

Syntax

The next property of the language is quite eloquent, clean and readable syntax.

Let’s consider the definition of class Person:

class Person (var name: String, var email: String)

That is it, seriously. Here we have a class with the primary constructor which takes two parameters and assigns their value to two public properties. Properties’ getters and setters were automatically generated by default but could be overridden if needed. A property can be made immutable just by replacing var with val.

In Scala you can override operators and invent your own (don’t go mad on this :) More than that, operators are in fact regular methods and method with one argument can be called by infix notation. So, a + b is a.+(b) and you can define your method +++ or thePlus which might be called as a +++ b.

If you have an experience in functional programming languages, you really should like the idea of pattern matching. Suppose you have a list of employees (developers and car drivers) and want to process it in some way. You could write:

employee match {
  case Developer(name, favoriteLanguage) =>;
    println(s"$name is a developer and likes $favoriteLanguage")
  case Driver(name, yearsOfExperience) =>;
    println(s"$name is a car driver and has $yearsOfExperience")
  case _ =>;
    println("Who's this guy?") // default match
}

(By the way, note string interpolators (liked it in your Perl? :)

Flexible syntax enables programmers to create domain-specific languages (Is this an advantage or disadvantage? Discussable question. However, some DSLs are used in Scala world, look at WordSpec in ScalaTest.)

Traits

I have mentioned object-oriented programming earlier. Scala has all widespread OOP features except multiple inheritance. Instead of it there is a thing called traits. Traits are mixins, modifications which you can add to your classes and add more than one. You can decorate class members (imagine useless mixin which doubles all integers you put into a list) or add new ones.

The standard library

The standard library of Scala, especially collections, is big and elaborated. Consider collections. There are both mutable and immutable versions of different collections, with also parallel and lazy variants of them.

Want to process a large list using all N cores of the CPU? Call the list’s par member and you will get a parallel variant of it, which have almost the same interface but operations will be paralleled when it is possible.

Or laziness:

// infinite stream, but computed lazily, only when needed
val stream = Stream.from(1)

// returns List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// and won't fail with stack overflow
stream.take(10).toList

Normal collections also can be transformed into the lazy version with Views:

List(1, 2, 3, 4, 5) view filter (_ > 2) map (_ * 2) force

filter and map will be applied in one pass, force will return the result back to the non-lazy form.

The standard library also has wide abilities of concurrent programming. There are Futures which represents the code run in some execution context (a thread pool, for simplicity). It is quite easy to run code in a concurrent thread:

val result = Future {
  val a = doExpensiveComputations()
  ...
  doMore(a)
}

In result there will be a future, i.e. eventually finished (or failed) computation. You can wait on it or set callbacks or (more often) you will apply some transformations to it and pass further without waiting it finished.

import scala.concurrent.{ExecutionContext, Future}
import ExecutionContext.Implicits.global

def getCurrentUserDataFromDB: Future[User] = ???
def getUserPosts(user: User): Future[List[Post]] = ???
def getUserComments(user: User): Future[List[Comment]] = ???
def createResponse(user: User,
                   posts: List[Post], 
                   comments: List[Comment]): Response = ???

def createResponseForCurrentUser: Future[Response] = {
  // Run fetching the user from the database
  val currentUser = getCurrentUserDataFromDB
  // Transform fetched user into list of posts
  // by getting them from the DB
  val postsFuture = currentUser flatMap { user => getUserPosts(user) }
  // Transform fetched user into list of comments
  // by getting them from the DB
  val commentsFuture = currentUser flatMap { user => getUserComments(user) }
  // for here is similar to Haskell do-notation --
  // syntactic sugar flatMaps and maps.
  // If any of futures fails, the result also will fail.
  for {
    user <- currentUser
    posts <- postsFuture
    comments <- commentsFuture
  } yield createResponse(user, posts, comments)
}

It is useful for creating non-blocking, reactive applications (look at Play web framework for example). Of course, it is up to you which execution context is used to run the future.

Functional programming

Apart from OOP, Scala also (and firstly) is a functional language. It has lots of FP stuff such as first-class higher-order functions, currying, partial application, tail recursion elimination, immutability, laziness, already mentioned powerful type system including monads etc.

Let’s look at laziness. For example, your object contains some field with the result of a very expensive computation. You just write:

lazy val theField = computeTheField()

and it will be computed only when and if it is called. Very convenient. I have also mentioned about lazy collections earlier.

Collections, futures and some other things are good old monads, you can do flatMap on them (equivalent to Haskell’s bind). Other useful monads are Try encapsulating computation which might fail with exception and Option which encapsulating value which might not exists, analogous to Haskell’s Maybe (goodbye NullPointerException, I won’t miss you).

Do you want more functional magic and type-foo, all these lenses, arrows and stuff? Look at Typelevel stack, especially scalaz, you will be satisfied.

Actors and Akka

Actor model is another use-proven model of concurrency, employed by Erlang and some other languages including young but promising Rust. Scala also gives us the power of actor via great toolkit Akka.

Drawbacks

You have listened to an ode to Scala :) But all the languages also has drawbacks. Despite the fact the post is about advantages of Scala, I am going to mention some disadvantages.

Scala is complex. I don’t mean it is really difficult to learn it, but it requires some time and patience, especially if you are not familiar with functional programming paradigm. However, the learning curve IMHO is quite gradual. You can start writing in Java-in-Scala and improve step-by-step. Problems might arise in teams of developers with different levels of knowledge: a Scala ninja could write code difficult to maintain for a junior developer. This is a matter of discipline and management. There is an interesting attempt to formalize levels of expertise in Scala.

Another disadvantage is a slow compilation. The Scala compiler requires noticeable time compared to Java. This is because Scala is much more complex than Java and the compiler must do more work (e.g. type inference), but this work is done for you and (sometimes) instead of you :) Nevertheless, the performance is getting better from release to release.

Conclusion

This is why (from my point of view) Scala is cool. Anyway, it isn’t wise to make a cult of any programming languages, so it is just an opinion :)

If you want to dive more into the language:

Happy hacking.

P.S. Are you familiar with Scala? Like it? What about other languages? Write a couple of lines in comments :)