Scala, Six Months In
5 minsAfter switching jobs, I was introduced to Scala at my new workplace. I’ve compiled a list of things that I have learned until now. I’ve kept the comparisons to the languages themselves, instead of functionality that can be provided by libraries.
Nice Things
Immutability and Type Inference
Declaring local variables in idiomatic Scala starts off by declaring it val
, which makes the reference immutable, then change it to var
if you really need to mutate it (so far I’ve never found the need to do that). Contrast that with Java, which is the other way around (declare a final
variable if you want immutability, otherwise it is mutable by default). It’s much easier to reason about the behaviour of these variables when you don’t have to worry that the reference can be changed later on.
Also nice is type inference:
val myString = "Hello, World." //myString is of type String
Java only recently got this in Java 10.
Null Safety
Even though Optionals have been part of the Java standard library since Java 8, few libraries use it in their APIs which forces you to deal with the existence of null references. However in Scala, the use of Options is idiomatic, which when combined with pattern matching, allows you to handle non-existence separately from error values. That is the biggest reason why null pointer exceptions are such an ubiquitous pain in the ass in Java.
Case Classes
Compare this:
public class MyPojo {
private String name;
private Integer year;
public MyPojo(String name, Integer year) {
this.name = name;
this.year = year;
}
public String getName() {
return name;
}
public Integer getYear() {
return year;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyPojo myPojo = (MyPojo) o;
return name.equals(myPojo.name) &&
year.equals(myPojo.year);
}
@Override
public int hashCode() {
return Objects.hash(name, year);
}
@Override
public String toString() {
return "MyPojo{" + name + "," + year + '}';
}
}
with the equivalent:
case class MyCaseClass(name: String, year: Int)
It’s really refreshing being able to just define your data in a one-liner class with sensible defaults for printing and comparison. Even though all the methods in the Java example were generated automatically by Intellij, there’s so much more boilerplate than in Scala.
Pattern Matching
def makeADecision(argument: Option): Unit = argument match {
case Some(_) => println("Has a value")
case None => println("No value in argument")
}
Yep, switch-case on steroids! No more calling instanceof()
and casting the object to a child class. Then again there’s a JEP for pattern matching in Java.
Concepts
Functional Programming
A monad is just a monoid in the category of endofunctors, what’s the problem?
There’s a lot of literature explaining monads, so I won’t presume to be able to explain them here, but most data structures in the Scala collections library, as well as things like Futures and Options are monads and therefore express computation in an easily composable way.
Types Are Your Friend
I especially liked learning about sealed traits, which when paired with pattern matching, lets me actually catch more errors at compile time due to exhaustiveness checking. That’s kind of the point of having an explicit type system anyway.
Typeclasses
Separate your data and logic! Though this uses scary “implicit” variables/methods to do so… Here’s a good introduction.
… Not So Nice Things
Compilation Speed
It’s a lot slower to compile Scala as compared to Java. Enough that the job that only checks if the pull request compiles successfully regularly takes five minutes to complete on a typical build agent in our Continuous Integration setup.
Simple Complex Build Tool
This is subjective, but sbt is one of the more complicated build tools that I have come across. Till now, I’ve mainly gotten around that problem by copying sbt task definitions from other existing projects, but I despair of actually understanding it.
Conclusion
In conclusion, I think there are many language design choices in Scala that actually make it nice to work in as compared to Java. Then again I used to work in a Java 7/8 shop. Nowadays Java 11 has incorporated many new language features inspired by what other languages are doing, so YMMV.