Peter brings us this solution:

(defn penultimate [xs]
  {:doc  "P02 (*) Find the last but one element of a list."
   :pre [(seq? xs)]}
  (loop [ret (first xs) xs xs]
    (if (next xs)
      (recur (first xs) (next xs))
      ret)))

I can not comment much, since I’m no Clojure developer. In particular I would like to know what recur does? A generic macro to do recursion on a function? Seems interesting…

This is my solution in Scala:

def penultimate[T](list: List[T]): T =
  list match {
    case List(first, last) => first
    case first :: second :: rest => penultimate(second :: rest)
    case _ => error("Can not find penultimate of this list: " + list)
  }

Using pattern matching, it does the following:

  • if it matches a list consisting of only two elements (first and last) return the first one
  • if it matches a list consisting of a least two elements and a rest, do recursion using the second and the rest
  • in any other case the list has an unacceptable for, raise an error

Note the two matching styles for a list. The first one using the de-structuring of the List (unapply behind the scenes) and the second using the “consing” of list-elements.

This implementation either returns the sought element, or it raises an error. It might be a cleaner, more idiomatic Scala implementation to return an Option[T] instead. Let’s explore that possibility:

def penultimate[T](list: List[T]): Option[T] =
  list match {
    case List(first, last) => Some(first)
    case first :: second :: rest => penultimate(second :: rest)
    case _ => None
  }

It can now be used like this:

penultimate(myList) map { element => /* do something with element */ }

Or, if one wants to handle the case where None is found:

penultimate(myList) getOrElse { /* no penultimate found, deal with this */}

Or, to handle both cases:

penultimate(myList) map { element => 
  /* do something with element */ 
} getOrElse { 
  /* no penultimate found, deal with this */
}