Reputation: 37
I have a problem here from 99 scala problems (http://aperiodic.net/phil/scala/s-99/p03.scala) that I am trying to figure out how it works. I'm fairly new to Scala. I was able to complete this challenge with a similar solution using pattern matching and recursion however mine did not consider the list in the matching. My code is below:
def nth[A](k: Int, l: List[A]): A = k match {
case 0 => l.head
case _ => nth(k-1, l.drop(1))
}
and this seemed to do the job. However, there's no error checking if the list is Nil. The solution 99 scala problems provides is:
def nthRecursive[A](n: Int, ls: List[A]): A = (n, ls) match {
case (0, h :: _ ) => h
case (n, _ :: tail) => nthRecursive(n - 1, tail)
case (_, Nil ) => throw new NoSuchElementException
}
What I dont understand is
case(0, h:: _ )
and
case(n, _ :: tail)
What is the author doing here? I understand :: appends whatever is on the left to the beginning of whats on the right but I'm not sure exactly what is happening. Can anyone enlighten me?
Thank you!
Upvotes: 1
Views: 1411
Reputation: 5023
Basically, it is pattern matching expression. That is why Scala pattern matching is so powerful, so we can drop some heavy visitor pattern like Java (out of this topic).
A simple example:
case class User(name: String, age: Int)
def doStuff(user: User) = user match {
case User(_, age) if age > 100 => println("Impossible!")
case User(name, _) => println("hello " + name)
}
In this case, _ :: tail just means I want to get the reference of the tail.
Upvotes: 1
Reputation: 548
The :: operator is used to extract the head and the rest of the list (the tail).
Here:
case(0, h :: _ )
only the head is relevant so the tail doesn't get a reference.
And Here:
case(n, _ :: tail)
only the tail is relevant so the head doesn't get a reference.
You can also use:
case(0, head :: tail)
case(n, head :: tail)
(i.e. giving both parts a reference) and get exactly the same result.
Upvotes: 2