The keys to understanding pattern matching are to understand that x :: y will only match a list with one x element, followed by the rest of the list y (which may be just Nil , or there may be many elements), and that _ means "here should to be something, but we will not name it. " (And that matches occur in order and end with Nil .)
You are correct that [A] is a generic type.
So the first line:
case h :: _ :: Nil => h
says that if our list looks (conceptually) Node(h) -> Node(whatever) -> Nil , then we return h . This is exactly a two-item list with the first item selected. Note that Nil does not match an arbitrary tail of the list; it matches only the end of the Nil list item. This is because of the rule that Scala uses to distinguish between two: lowercase variables are treated as wildcards, which must have the corresponding value filled in, while uppercase variables are treated as constants for matching. (If you must match the name in lowercase, you can if you surround it with reverse windows.)
Ok, now suppose this is not a two-item list. Then, if it is not empty, it will match
case _ :: tail => penultimateRecursive(tail)
therefore, if we do not have a two-element list, we discard the first element and try again. Finally, if we somehow did not finish the two-element list, we move on to
case _ => throw new NoSuchElementException
and you're done. (This could also be case Nil , in fact, as this is the only possibility that does not match the other two elements.)
Rex kerr
source share