What exactly happens when you evaluate expression: Seq(1,2,3)
?
I am new to Scala and I am now a bit confused about various collection types. Seq is a tr
What exactly happens when you evaluate expression:
Seq(1,2,3)
?
In Scala, foo(bar)
is syntactic sugar for foo.apply(bar)
, unless this
also has a method named foo
, in which case it is a method call on the implicit this
receiver, i.e. just like Java, it is then equivalent to this.foo(bar)
.
Just like any other OO language, the receiver of a method call alone decides what to do with that call, so in this case, Seq
decides what to do.
Seq is a trait, right?
There are two Seq
s in the standard library:
So when you call it like that
Seq(1,2,3)
it must be some kind of a companion object? Or not?
Yes, it must be an object, since you can only call methods on objects. You cannot call methods on types, therefore, when you see a method call, it must be an object. Always. So, in this case, Seq
cannot possibly be the Seq
trait, it must be the Seq
object.
Note that "it must be some kind of a companion object" is not true. The only thing you can see from that piece of code is that Seq
is an object. You cannot know from that piece of code whether it is a companion object. For that, you would have to look at the source code. In this particular case, it turns out that it is, in fact, a companion object, but you cannot conclude that from the code you showed.
Is it some kind of a class that extends Seq?
No. It cannot possibly be a class, since you can only call methods on objects, and classes are not objects in Scala. (This is not like Ruby or Smalltalk, where classes are also objects and instances of the Class
class.) It must be an object.
And most importantly what is the type of the returned value?
The easiest way to find that out is to simply look at the documentation for Seq.apply:
def apply[A](elems: A*): Seq[A]
Creates a collection with the specified elements.
A
: the type of the collection's elementselems
: the elements of the created collection- returns a new collection with elements elems
So, as you can see, the return type of Seq.apply
is Seq
, or more precisely, Seq[A]
, where A
is a type variable denoting the type of the elements of the collection.
Is it Seq and if yes, why is not explicitly the extension class instead?
Because there is no extension class.
Also, the standard design pattern in Scala is that the apply
method of a companion object returns an instance of the companion class or trait. It would be weird and surprising to break this convention.
Also in REPL I see that the contents of the evaluated expression is actually a List(1,2,3), but the type is apparently Seq[Int].
The static type is Seq[Int]
. That is all you need to know. That is all you can know.
Now, Seq
is a trait
, and traits cannot be instantiated, so the runtime type will be some subclass of Seq
. But! You cannot and must not care, what specific runtime type it is.
Why is not an Indexed collection type, like Vector? What is the logic behind all that?
How do you know it is not going to return a Vector
the next time you call it? It wouldn't matter one bit, since the static type is Seq
and thus you are only allowed to call Seq
methods on it, and you are only allowed to rely on the contract of Seq
, i.e. Seq
's post-conditions, invariants, etc. anyway. Even if you knew it was a Vector
that is returned, you wouldn't be able to do anything with this knowledge.
Thus, Seq.apply
returns the simplest thing it can possibly return, and that is a List
.