docs.scala-lang
docs.scala-lang copied to clipboard
we do not have a method with name tailOption in the scala collections
Written in this part of the scala3 book collections-methods
tail throws an java.lang.UnsupportedOperationException if the list is empty, so just like head and headOption, there’s also a tailOption method, which is preferred in functional programming.
But we do not have a method with name tailOption in the scala collections
Hello, good catch! Would you be interested in contributing a fix?
@julienrf Is this issue still relevant?? I see we have "last" and "lastOption" already defined which works just like "tail" and "tailOption".
@julienrf Is this issue still relevant?? I see we have "last" and "lastOption" already defined which works just like "tail" and "tailOption".
tailOption would return Option[Collection[T]] because it is the remaining collection with only the first element removed, or None for an empty collection.
lastOption returns Option[T] because it is the last element of the collection, (which could be the first element for a singleton collection) or None for an empty collection
The book should be fixed. The more convenient way, almost always, to do "tailOption" is to do drop(1). It doesn't cover every possible use case, but it covers enough so that the clutter of two more methods (tailOption and initOption) isn't worth it.
The few odd cases where you actually need tailOption should be handled with pipe instead, especially if you're using Scala 3 where you can define a fully efficient one:
extension [A](a: A)
inline def pipe[B](inline f: A => B): B = f(a)
Any time you have an urge to write
someBigThingYouDontWantToRepeat.tailOption.map{ tail =>
foo(tail)
}
you can choose one of the following excellent alternatives, and with the power of pipe you have many more options to do non-tailOptiony things, too.
someBigThingYouDontWantToRepeat.pipe{ xs =>
if xs.isEmpty then None
else Some(foo(xs.tail))
}
someBigThingYouDontWantToRepeat.pipe{ xs =>
if xs.isEmpty then someDefault
else foo(xs.tail)
}
someBigThingYouDontWantToRepeat.pipe{ xs =>
xs.headOption{ head =>
foo(head, xs.tail)
}
}
someBigThingYouDontWantToRepeate.match{
case head +: tail => foo(tail)
case _ => someDefault
}