Reputation: 79
I have this
val x = List(1,2,3,4,5,6,7,8,9)
I want to take the items of the list from 3 to the end of the list and create a new list with them without changing state, and get this:
List(4,5,6,7,8,9)
Upvotes: 2
Views: 436
Reputation: 369458
As stated in @Jubobs' comment and @Yuval Itzchakov's answer, the answer is to use the scala.collection.immutable.List.drop(n: Int): List[A]
method of lists, whose implementation you can find in src/library/scala/collection/immutable/List.scala
.
However, because of the importance of List
in the Scala ecosystem, this method is aggressively optimized for performance and not indicative of good Scala style. In particular, even though it is "externally pure", it does use mutation, side-effects and loops on the inside.
An alternative implementation that doesn't use any mutation, loops or side-effects might look like this:
override def drop(n: Int): List[A] =
if (n == 0) this else tail drop n-1
This is the trivial recursive implementation. Note: this will throw an exception if you try to drop more items than the list has, while the original one will handle that gracefully by returning the empty list. Re-introducing that behavior is trivial, though:
override def drop(n: Int): List[A] =
if (n == 0 || isEmpty) this else tail drop n-1
This method is not just recursive, but actually tail-recursive, so it will be as efficient as a while
loop. We can have the compiler yell at us if that isn't true by adding the @scala.annotation.tailrec
annotation to the method:
@scala.annotation.tailrec override def drop(n: Int): List[A] =
if (n == 0 || isEmpty) this else tail drop n-1
Upvotes: 5
Reputation: 149538
As mentioned in the comments, List.drop
does exactly that:
val x = List(1,2,3,4,5,6,7,8,9)
val reduced = x.drop(3)
The implementation looks like this:
override def drop(n: Int): List[A] = {
var these = this
var count = n
while (!these.isEmpty && count > 0) {
these = these.tail
count -= 1
}
these
}
Upvotes: 2