10 More Scala Features Most* Java Developers Love

Posted on 07 February 2017


(*) Please don’t take the title too seriously. I have no empirical evidence that it is actually the case (that most Java developers love these features). I know some do, me included. Well, honestly, I just kind of liked the title of the first blog post when I wrote it, and decided to stick with the “love” theme.

In my first blog post, 10 Scala Features Most Java Developers Love, I assembled a top 10 list of Scala features I wouldn’t want to miss, and that I found more or less universally liked in conversations with other Java developers. There were a few items back then that would have deserved to also be on the list, and some more that have been pointed out to me after the post was published. So I decided to do this sequel.

11. The REPL

Scala comes with a Read-Eval-Print-Loop, short REPL. You can quickly start an interactive Scala shell on the command line and try out any code snippet you like. If you need additional libraries, sbt console will give you a REPL that will have all the library dependencies of your sbt project readily available.

You can even try the Scala REPL online, with https://scastie.scala-lang.org or https://scalafiddle.io.

Update: Java 9 will also have a REPL called JShell, see https://openjdk.java.net/jeps/222.

12. Imports

Scala’s imports have some additional flexibility compared to Java’s. Firstly, you don’t have to put all imports at the beginning of the file, you can import something right before you use it. Why is this useful? Because now you can limit the scope of the import - it will only be imported within the current block, and not pollute any larger namespace.

You can rename classes on import, which will be loved by anyone who’s used java.sql.Date and java.util.Date in the same file:

import java.sql.{Date => SDate}

As * is a valid identifier in Scala, it can’t be used as a wildcard. Use the underscore to import all classes of a package:

import java.sql._

You can combine the wildcard and renaming to import all classes of a package except one:

import java.sql.{Date => _, _}

13. Tail Call Optimization

Java does not have any sort of compiler optimization for tail recursion, which is quite the drawback if you want to program in a functional style. A textbook example for a recursive function is calculating the factorial of a natural number:

def factorial(i: Int): Long = {
  @tailrec
  def fact(i: Int, accumulator: Int): Long = {
    if (i <= 1) accumulator
    else fact(i - 1, i * accumulator)
  }

  fact(i, 1)
}

In Java, this implementation will quickly lead to a StackOverflowError as you try it with bigger numbers. The Scala compiler however will, just like FP language compilers do, convert it to a simple loop, it will run just as efficiently as a for loop in Java. The optional @tailrec annotation tells the compiler that you believe it is in fact tail recursive, so the compiler will warn you if it can’t do any tail call optimization.

Again, to me this is a major drawback in Java. It’s quite the mystery to me why the Java compiler doesn’t optimize tail recursive calls. How can you live without?

14. Compile to JavaScript

Yes, you can compile Scala to JavaScript and run it in any web browser. This is provided by a compiler plugin maintained by the ScalaJS project. It’s absolutely awesome, try it out!

15. “Operators”

In Scala, you can use pretty much any symbol in method names - so that thing that looks like an operator (defined in the language specification) to you is probably just a method (defined by some library developer in a regular Scala class).

For example Ordered, mentioned about in the section about traits. It’s just methods:

trait Ordered[A] {
  def < (that: A): Boolean = ...
  def > (that: A): Boolean = ...
  def <= (that: A): Boolean = ...
  def >= (that: A): Boolean = ...

Scala has a simple convention: If a method has one parameter, you can omit the dot and parentheses - so you get a nice infix notation:

1.+(2)   // 1 + 2
1.<(2)   // 1 < 2

Another example is to use the method ! to send a message to an actor in Akka. Which translates to tell in the Java API - but does travelAgent ! BookFlight not read 10x better than travelAgent.tell(BookFlight, self())? With the added bonus that you can use ? for the ask method. C++ programmers will look at Scala code and say, “sure, operator overloading”, but it really isn’t - it’s just methods, and you name them any way you see fit.

16. Tuples

While the collections are for elements of the same type, tuples are sequences of fixed length, of values of possibly different types. This is such a basic concept and it feels so natural to group values in this way, once you’ve gotten used to it, it’s rather puzzling how Java developers can live without it, and how a number of proposals to include them in the language have been rejected.

To create a tuple, just write the values in parentheses.

scala> val tup = ("intAndDouble", 1, 1.9)
tup: (String, Int, Double) = (intAndDouble,1,1.9)
scala> tup._1
res0: String = intAndDouble
scala> tup._3
res1: Double = 1.9

17. Nested Methods

You can define a method within a method, and thus make it private to the enclosing method.

A classic example is a Fibonacci function, that could look something like this:

def fib(n: Int): Int = {
  def innerfib(a: Int, b: Int, n: Int): Int =  if (n > 0) innerfib(b, a+b, n-1) else a
  innerfib(0, 1, n)
}

18. Named and Default Arguments

In Scala, every method argument can be referred to by its name by the caller. And for every argument, you can provide a default value, thus making the argument optional.

case class Time(hours:Int = 0, minutes:Int = 0)
scala> Time()
Time(0,0)
scala> Time(9)
Time(9,0)
scala> Time(minutes = 15)
Time(0,15)
scala> Time(hours= 10, minutes = 15)
Time(10,15)

So instead of overloading methods or constructors with all possible permutations of the argument list, just have one and provide defaults, and the caller can decide which ones to override.

19. Multiline String Literals

In Scala, you can easily create a multiline string by using a “triplequote”, i.e. """. For example:

val s = """This is
           a multiline
           String"""

This is already great, but as this takes your input very literally, the indentation tabs or spaces on the left will be part of your quoted string. So it gets even better: You can use |and stripMargin to get a nicely formatted multiline string:

val query = """SELECT *
              |FROM MYTABLE
              |WHERE id = 781""".stripMargin

I’m not the only person missing this feature, see for example http://blog.jooq.org/2015/12/29/please-java-do-finally-support-multiline-strings/.

Update: It seems we’ve been heard, and it’s going to be in Java 12: https://openjdk.java.net/jeps/326.

20. No Checked Exceptions

This is a bit of the odd one out, as it’s about a “feature” that Scala doesn’t have: In Scala, there are no checked exceptions. I’m not going to discuss the reasons why checked exceptions aren’t great here, as it has been done at many other places (e.g. http://wiki.c2.com/?TheProblemWithCheckedExceptions). If you’ve done some programming with higher order functions, you’ve probably already discovered for yourself that checked exceptions are not the solution.

Fin

This is it, or rather, I’ll leave it at that, 20 is a good number. Of course there are many other things I personally find extremely valuable in Scala, but not all of them might be as accessible and obvious to the outsider as the twenty listed here.

Unfortunately discussions about Java vs. Scala often quickly escalate into flame wars about Object-Oriented vs. Functional Programming, sbt vs. Maven vs. Gradle, Haskell vs. Go, and the importance of Category Theory.

I hope, and that’s the spirit these two posts have been written in, that people are able to see this whole other side to it, that often gets buried in the more dogmatic exchanges: If you are - like me - used to developing in Java, there are so many little things in Scala that just make your everyday day life easier. By saving you from typing boilerplate, providing a powerful API, or giving you that little extra flexibility.

 



Back