P01 - Find the last element of a list
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?).