I am teaching myself Scala. In particular, I am following the book Functional programming in Scala by Chiusano et al. Chapter 3 presents you with an implementation of a linked list:
sealed trait List[ A]
case object Nil extends List[Nothing]
case class Cons[ A](head: A, tail: List[A]) extends List[A]
object List{
def sum(ints: List[Int]): Int = ints match{
case Nil => 0
case Cons(x, xs) => x sum(xs)
}
def product(ds: List[Double]): Double = ds match {
case Nil => 1.0
case Cons(0.0, _) => 0.0
case Cons(x, xs) => x*product(xs)
}
def apply[A](as: A*): List[A] =
if (as.isEmpty) Nil
else Cons(as.head, apply(as.tail: _*))
}
and asks you to implement the function tail, that should return a list with all values but the first. I have implemented it in the following way:
def tail(ints: List[Int]): List[Int] = ints match {
case Cons(x, xs) => xs
}
(Partly, because I do not know how to implement the case in which the passed list is Nil).
However, when I have tested it on List(1,2,3)
, the following is returned:
Cons(2,Cons(3,Nil))
instead of:
List(2, 3)
which is what I was expecting. Besides, I am using intellij, and the IDE won't let me write List(1,2,3).tail
, but only tail(List(1,2,3))
.
Can anyone tell me what I am doing wrong? Why is my tail implementation giving me such a strange return value? Why won't the IDE let me write List(1,2,3).tail
? How to implement the case in which the list passed is Nil?
CodePudding user response:
Why won't the IDE let me write
List(1,2,3).tail
?
What you've written is a stand-alone method that takes a List
as a passed-in parameter. If what you want is to have a List
return its own tail
then you're actually half way there.
The Cons
already has a tail
member, you just have to promote it to the List
definition and give the Nil
a reasonable implementation.
sealed trait List[ A] {
val tail: List[A]
}
case object Nil extends List[Nothing] {
lazy val tail =
throw new UnsupportedOperationException("tail of empty List")
}
case class Cons[ A](head: A, tail: List[A]) extends List[A]