I am trying to use the :::
method (is this an operator method?) from List
. Okay I know what it is doing now after typing in two lists in the REPL and seeing what was going on. However the API definition of the ::: method was hard to read and understand. I only "got it" by reading what it "returns".
def :::[B >: A](prefix: List[B]): List[B]
Adds the elements of a given list in front of this list.
prefix The list elements to prepend.
returns list resulting from the concatenation of the given list prefix and this list.
Example: List(1, 2) ::: List(3, 4) = List(3, 4).:::(List(1, 2)) = List(1, 2, 3, 4)
In particular what does this part mean: [B >: A](prefix: List[B])
. I mean I was able to understand what the method returns by reading what the method returns and playing with it. For the future, I would like to be able to read the API for a different method and try to understand everything. That is why I am asking this question.
The two answers are both correct. You only have to remember that A
is the type parameter of your current list, and B
is the type parameter of the list you are supplying to :::
If you are not yet confident, you can try your own definition of List
class MyList[+A]{
def :::[B >: A](prefix: MyList[B]): MyList[B] = new MyList[B]()
}
class Animal
class Dog extends Animal
class Pig extends Animal
class Rock
And now you can test in the REPL:
scala> new MyList[Dog]
res0: Test.AkkaTest.MyList[Test.AkkaTest.Dog] = Test.AkkaTest$MyList@190a0d51
scala> new MyList[Pig]
res1: Test.AkkaTest.MyList[Test.AkkaTest.Pig] = Test.AkkaTest$MyList@1db5d2b2
scala> res0:::res1
res2: Test.AkkaTest.MyList[Test.AkkaTest.Animal] = Test.AkkaTest$MyList@25927275
scala> new MyList[Rock]
res3: Test.AkkaTest.MyList[Test.AkkaTest.Rock] = Test.AkkaTest$MyList@49f85a86
scala> res3:::res0
res4: Test.AkkaTest.MyList[ScalaObject] = Test.AkkaTest$MyList@42130c2
scala> res0:::res3
res5: Test.AkkaTest.MyList[ScalaObject] = Test.AkkaTest$MyList@6f24d504
So you know should have understood that the ::: concatenates two list and creates a list whose generic type is the first common ancestor. This is because the type list is covariant, so for example you might think that, in case of res3 and res0 the compiler does the following:
- A is Rock B is Dog, B is not a parent class of A, maybe I should throw compiler error?
- But since MyList is covariant, MyList[Dog] is a subclass of MyList[ScalaObject].
- Cool, ScalaObject is a parent class of Rock, so I will create a list of ScalaObject
[B >: A]
means that the method is generic and takes one type argument called B
that must be a supertype of A
. (prefix : List[B])
means that it takes one actual argument called prefix
of type List[B]
.
If it wasn't for subtypes this would be written def :::(prefix: List[A]): List[A]
, the [B >: A]
just lets you, say, prefix a List[Animal]
onto a List[Cat]
, getting a larger List[Animal]
.