Fork me on GitHub

Graceless Failures

Tips, tricks, missteps, and minor revelations on the path to Scala wisdom.

Accumulation

It’s a pretty common operation to take a list of stuff and accumulate the items. For example, if I have a collection of word frequencies and I want to aggregate the counts by word.

The “Java” imperative way of doing this is to create a HashMap of stuff and populating the HashMap. For example (this is Java-style Scala code):

def accumulate(in: Seq[(String, Int)]): Seq[(String, Int)] = {
  val map = new HashMap[String, Int]

  for ((str, cnt) <- in) {
    if (map.isDefinedAt(str)) map(str) = map(str) + cnt
    else map(str) = cnt
  }

  map.toList
}

What are we doing? We’re creating some state and iteratively updating the state.

My preferred way of doing this is thinking about the issue as “transformative”. We’re transforming the input to the output, without mutating anything.

def acc(in: Seq[(String, Int)]): Seq[(String, Int)] =
  in.foldLeft[Map[String, Int]](Map.empty){
    case (map, (str, cnt)) => map + (str -> (map.getOrElse(str, 0) + cnt))
  }.toList

The transformative approach is shorter and I believe, sweeter.