The first problem is to find the last element of a list.

This is Peter’s Clojure version:

(defn my-last [input]
  "P01 (*) Find the last element of a list."
  (if (next input)
    (recur (next input))
    (first input)))

And here is my Scala version:

def last[T](list: List[T]): T =
  list match {
    case List(only) => only
    case first :: rest => last(rest)
    case Nil => error("An empty list has no last element")
  }

Some things to note about the Scala version:

  • It is, of course, type-safe. It won’t accept anything but a list.
  • It is generic: it will work on lists of anything.
  • Because it’s recursive, the return type has to be declared.
  • You get a runtime-error if the list is empty

Because it’s generic and due to Scala’s type inference this will also work:

scala> last(List(1, 2, true, "five", 8))
res0: Any = 8

Scala will just infer to the most immediate matching super-class. In this case: Any.

But there is something disturbing in this implementation, however: raising an error if the list is empty. The Clojure version simply returns nil instead. Both solutions are not quite acceptable to me.

Having to deal with runtime-errors or magic “nulls” is something that as a Scala developer you are inclined to avoid. Fortunately Scala makes it very easy to do so, by switching to Option[T]:

def last[T](list: List[T]): Option[T] =
  list match {
    case List(only) => Some(only)
    case first :: rest => last(rest)
    case Nil => None
  }

Now, the function might return Some[T] or None (it reads like English, doesn’t it?).