Reputation: 374
I think that I would make some mistakes in below explanation for my question but within my limit understanding I cannot figure out how to correctly describe the issue
The scala code snipet as below:
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 apply[A](as: A*):List[A] =
if (as.isEmpty) Nil
else Cons(as.head, apply(as.tail: _*))
}
If I create object x as: val x = List(1,2,3)
I pass into companion object "List", three numbers as : 1 ,2 and 3 Then, internally, function apply is triggered At the moment of construction, how could these three numbers has method/attribute like: as.head and as.tail
I guess it could be possibly a kind of pattern matching, but even that, I could not understand the magic that number "as" now has method/attribute for ".head" and ".tail"
Upvotes: 0
Views: 66
Reputation: 51271
Try this in the REPL.
scala> def apply[A](as :A*) = as
apply: [A](as: A*)Seq[A]
So the compiler considers the varargs variable, as
, to be of type Seq[A]
, which is where the .head
and .tail
comes from.
Upvotes: 1
Reputation: 5596
The trick is that as: A*
is a variable argument what is converted to an array-like object, actually a WrappedArray$ofInt
in your case.
WrappedArray
has head
and tail
methods.
You can extend your definition of List
object to see A*
's class like this:
object List {
def apply[A](as: A*):List[A] = {
println(as.getClass)
if (as.isEmpty) Nil
else Cons(as.head, apply(as.tail: _*))
}
}
For a more detailed explanation check e.g. this .
Upvotes: 0