Stijn
Stijn

Reputation: 551

Instantiating objects on both sides of assignment operator in Scala; how does it work

I want to understand the mechanism behind the following line:

 val List(x) = Seq(1 to 10)

What is the name of this mechanism? Is this the same as typecasting, or is there something else going on? (Tested in Scala 2.11.12.)

Upvotes: 4

Views: 140

Answers (4)

senjin.hajrulahovic
senjin.hajrulahovic

Reputation: 3191

This technique is called object destructuring. Haskell provides a similar feature. Scala uses pattern matching to achieve this.

The method used in this case is Seq#unapplySeq: https://www.scala-lang.org/api/current/scala/collection/Seq.html

Upvotes: 5

Tim
Tim

Reputation: 27356

I suspect that your problem is actually the expression

Seq(1 to 10)

This does not create a sequence of 10 elements, but a sequence containing a single Range object. So when you do this

val List(x) = Seq(1 to 10)

x is assigned to that Range object.

If you want a List of numbers, do this:

(1 to 10).toList

The pattern List(x) will only match if the expression on the right is an instance of List containing a single element. It will not match an empty List or a List with more than one element.

In this case it happens to work because the constructor for Seq actually returns an instance of List.

Upvotes: 6

Alexey Romanov
Alexey Romanov

Reputation: 170735

You can think of

val <pattern> = <value>
<next lines>

as

<value> match {
  case <pattern> => 
    <next lines>
}

This doesn't happen only when <pattern> is just a variable or a variable with a type.

Upvotes: 3

pme
pme

Reputation: 14803

The mechanism is called Pattern Matching.

Here is the official documentation: https://docs.scala-lang.org/tour/pattern-matching.html

This works also in for comprehensions:

for{
 People(name, firstName) <- peoples
} yield s"$firstName $name"

To your example:

val List(x) = Seq(1 to 10)

x is the content of that List - in your case Range 1 to 10 (You have a list with one element).

If you have really a list with more than one element, that would throw an exception

val List(x) = (1 to 10).toList // -> ERROR: undefined

So the correct pattern matching would be:

val x::xs = (1 to 10).toList

Now x is the first element (head) and xs the rest (tail).

Upvotes: 7

Related Questions