Scala is a really nice programming language to work with and is easy for devs coming from the Java world (like me) to pick up, due to the fact it runs on the JVM. I thought I’d share the six main reasons I’ve been using Scala for many of my projects at the moment.
1. Scala feels like a dynamically typed language, but without the suck
That’s a bit harsh - I enjoy using dynamically typed languages, but generally speaking I tend to lean towards statically typed languages because:
- When using a library, I know what to pass into functions. I don’t have to play the guessing game (or wade through library code that really should be encapsulated away from me) when documentation is poor.
- Intelligent code completion.
- Compile time type checking.
I know there are counter benefits to using dynamically typed languages and one of the things I love about dynamically typed languages is that they are generally much more succinct and allow you knock things up in a fraction of the time of statically typed languages where you can feel like you are getting bogged down with the verbose syntax - you have to specify types everywhere!
Scala strikes a nice balance in this regard. Declaring variables is concise as you need not declare the type:
:::scala
val animal = "Cat"
Despite the lack of a type, Scala is a statically typed language. Functions must declare their argument types, but for most other situations Scala can infer type (variable declarations, function return types, etc). There are some situations when this is not true, for example, if you are only declaring a variable and not assigning anything to it, you must specify the type. Also some overloaded and recursive functions must declare a return type, but for the most part Scala’s type inference keeps your code nice and concise.
Scala is also succinct is many other ways, which leads be to….
2. Case classes
Case classes are the Scala equivalent of Java POJOs - objects you use to hold state and often don’t do a whole lot else. The difference is that Scala case classes don’t have all the boilerplate cruft of Java POJOs. Here is a case class in Scala:
:::scala
case class Animal(type:String, sound:String)
If you omit the case
keyword you’d have a standard scala class, but the presence of the case
keyword auto-magically gives the class these benefits for free:
- Auto-generated getter methods.
- Auto-generated equals() and hashCode() - based on all the class fields.
- Auto-generated friendly toString() - displays the class name and all the class fields.
- Auto-generated copy() method that can be used to create a copy of any objects of this class. The method takes arguments to change field values in the copy.
- No longer need to use the
new
keyword to instantiate objects of this class. - Pattern matching.
Note how only getter methods are generated, not setter methods. This is because Scala promotes the use of immutable objects (hence the copy method), however if you do want to create a mutable case class with setters as well as getters, you can use the var
keyword:
:::scala
case class Animal(var kind:String, var sound:String)
Pattern matching is a nice language feature in Scala. It allows you to use instances of your case classes along with wildcards in switch style statements:
:::scala
val bingo = Animal("Dog", "Woof");
bingo match {
case Animal(_, "Chirp") => println("This is an animal that chirps")
case Reptile(_, sound) => println("This is a animal of subtype Reptile which makes the sound: " + sound)
case Animal(_, _) => println("This is any animal")
}
3. Named and Default Arguments
For constructor and method arguments you can specify defaults:
:::scala
> class Animal(kind:String, sound:String="Woof")
> new Animal("Dog")
res1: Animal = Animal(Dog,Woof)
You can also use similar syntax when calling a constructor or method to reference arguments by name, rather than position:
:::scala
> val cat = new Animal(kind="Cat", sound="Meow")
cat: Animal = Animal(Cat,Meow)
This comes in useful when you have many default arguments and need to highlight which arguments you want to specify.
:::scala
> val tiger = cat.copy(sound="Roar!")
tiger: Animal = Animal(Cat,Roar!)
4. Awesome Collections Framework
You can do some really nice things with the core collections framework. It’s like the Guava, the Java library, but with nicer syntax. There is too much goodness to show here, but here are a few things you can do:
:::scala
> val animals = List(
Animal("Cat"),
Animal("Dog"),
Animal("Mouse")
)
> //map takes a function and uses it to transform each element in the list
> animals.map(animal:Animal => {
return animal.kind
})
res1: List[String] = List(Cat, Dog, Mouse)
> //Same as above, but short hand
> animals.map(_.kind)
res2: List[String] = List(Cat, Dog, Mouse)
> res2.filter(_.startsWith("D"))
res3: List[String] = List(Dog)
> res2.groupBy(_.length())
res4: Map[Int,String] = Map((3 -> List(Cat,Dog))(5 -> List(Mouse)))
5. Integration with Java Libraries
Java and Scala code can be used together. You can call Java code from within Scala and vice versa. This is great, because you can still use all the great Java libraries you know and love. It also means you can start writing Scala code in existing Java systems - you don’t have to go big bang and port everything to Scala to gain it’s benefits at once.
6. Scala Console
Type scala
in your terminal and you get the Scala console. This is a great sandbox for testing stuff and makes it real easy to start playing. It’s this same reason that made me fall in love with bash.
PS. I used the Scala Console to write the examples for this blog post :)
Comments !