1

I know that it's possible to easily pattern match against the head (or an arbitrary number of initial elements) and tail of a List:

val items = List(1, 2, 3, 4)
val first :: rest = items

println(first, rest) // 1, List(2, 3, 4)

However, I would like to do it the other way - can you use a pattern to get the init and last of the list?

val items = List(1, 2, 3, 4)
val rest ??? last = items

println(rest, last) // List(1, 2, 3), 4

In JavaScript this would look like:

const [...init, last] = items
Ian
  • 5,704
  • 6
  • 40
  • 72
  • 1
    I think this answer has what you're looking for: https://stackoverflow.com/questions/6697645/scala-get-first-and-last-elements-of-list-using-pattern-matching/43478668 – user14789609 Dec 14 '20 at 14:56

2 Answers2

3

You can use the :+ custom extractor object.

So the code would look like this:

val rest :+ last = items

However, note that this is equally inefficient than doing:

val last :: rest = items.reverse

But, if you then need to decompose rest again, then reversing it first will be more efficient.

Finally, remember both are unsafe since they will throw in case the List is empty.

  • Cool! Is there documentation on all the builtin extractor objects like this one anywhere? I checked here but I don't see it - https://www.scala-lang.org/api/current/scala/collection/immutable/List$.html – Ian Dec 14 '20 at 14:56
  • @lan uhm no AFAIK, in any case, there are not too many custom extractors in the stdlib. - What would you like to know? – Luis Miguel Mejía Suárez Dec 14 '20 at 15:04
  • I was just wondering what other ones are available. – Ian Dec 14 '20 at 15:30
1

This should work:

val xs :+ x = items

Check out: https://www.scala-lang.org/files/archive/api/2.12.0/scala/collection/Seq.html#:+(elem:A):Seq[A]

mfirry
  • 3,634
  • 1
  • 26
  • 36