A practical guide to breakOut
2017-05-27

In this post I will be reviewing scala.collection.breakOut from an application developer's perspective rather than a functional programming enthusiast. I will discuss why one would want to use it and how to recognize when it is applicable.

When I first saw breakOut, it seemed like an extremely intimidating concept and a little like black magic. It certainly didn't help that I found explanations of breakOut intermingled with the equally intimidating concept of CanBuildFrom. This is a shame because, with proper application, breakOut can make your code run faster. Let's consider the following code sample:

The full code sample can be found at github.

Why we care

val list = List("one", "two", "three", "four")

val expensiveMap = list      //type Map[Int, String] is infered by the compiler
  .map(n => n.length -> n)     //1
  .toMap                    //2

The problem with this code is that it is memory inefficient. We first create an intermediate list at line (1) and then convert it to a Map on line (2). Ideally we could do it all in one step. Well thanks to breakOut we can!

import scala.collection.breakOut
val list = List("one", "two", "three", "four")

val efficientMap: Map[Int, String] = list   //you need to specify the type
  .map(n => (n.length, n))(breakOut)

This results in the Map we want without the intermediate list. Win!

When to use

So when should we use breakOut? An easy way to remember when to use it is if we have the following list of conditions:

Conclusion

Scala has a robust immutalbe collections library, which has a tendency to make it more GC heavy. However, with some attention to the implementation details, it is possible to remain efficient and functional.