ilango
ilango

Reputation: 1287

How to interpret ::: from the Scala API for List?

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.

Upvotes: 1

Views: 543

Answers (3)

Edmondo
Edmondo

Reputation: 20080

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

Upvotes: 1

Ricky Clarkson
Ricky Clarkson

Reputation: 2939

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].

Upvotes: 2

sepp2k
sepp2k

Reputation: 370122

[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].

Upvotes: 4

Related Questions