Will.Whim

A weblog by Will Fitzgerald

Monthly Archives: June 2012

Scala partial functions, map, and filter

Yesterday, I was writing some code that needed to (1) go over a collection of stored database objects, conditionally convert some of these to another version of themselves, and filter out some of them. For some reason, I got myself tripped up on some very basic things, and so here are some notes for myself and perhaps for others. (There were some other things going on, for one, support website pagination, but I won’t discuss that here).

The simplest way to handle is to use filter and map on the collection. For example, let’s say we want to remove, from a collection of integers, all odd numbers, and halve all the remaining numbers if they are a multiple of 4:

scala> (1 to 12).filter{_ % 2 == 0}.map{i => if (i % 4 == 0) i/2 else i}
res43: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 2, 6, 4, 10, 6)

Simple enough, of course: filter, then map, though map then filter might make sense in other cases (but of course here there is less “work” if we filter first).

Another possibility was to use partial functions, using collect. This can allow mapping and filtering to take place in the same step. In Scala’s terms, a partial function is a function from only some values of its argument. For example, if a function only applied to even Ints, then this function would be partial. This is, in effect,what we are saying the filter step does above. So we can get the same effect using collect:

scala> (1 to 12).collect{case i if i % 2 == 0 => if (i % 4 == 0) i/2 else i}
res44: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 2, 6, 4, 10, 6)

It’s a tool to have in one’s toolbox, but I think the “filter, then map” is clearer code. Interestingly, the first version is even a little shorter than the second.

Advertisements