Reputation: 1772
I'm fairly new to Scala and I was wondering what the following line of code is doing:
class E{
val (a: A, b: B, c:C, d:D) = {
...
}
}
Is it making an assignment (because of the val?) and then executing the body?
Upvotes: 0
Views: 103
Reputation: 62855
It's execute the body, then destructure it's result:
val (a: A, b: B, c:C, d:D) = {
...
}
First, the body produces some result (which is expected to be tuple*), then this tuple broken down into it's elements, each element is assigned to a
, b
, c
and d
respectively.
You probably have seen this code in Java:
int x = 1, y = 2, z = 4;
// now x is 1, y is 2, z is 4
Or even this code in python:
>>> x, y = 1, 2
>>> x
1
>>> y
2
Scala takes this on the next level, with a feature called destructuring assignment, and while it doesn't allow Java and Python syntaxes, it's far more flexible because it allows you not only the similar experience (via using of tuples):
val (x, y) = (1, 2)
But also generalized and extensible concept of such use case of pattern matching, e.g. on arrays:
val xs = Array(1,2,3,4)
val Array(first, second, _*) = xs // _* mean I don't care about the rest of elements
// first: Int = 1
// second: Int = 2
On lists:
val head::tail = List(1,2,3,4)
head: Int = 1
tail: List[Int] = List(2, 3, 4)
And in many other cases.
You may think that this operation somehow destroys original value, but usually it's not (unless custom extractor function is side-effecting)
* tuple is a kinda like immutable collection of finite known size, each element of it can be directly addressed which ._x
method, like foo._1
for the first one, foo._2
for the second one. Tuples in scala has syntax sugar -- braces.
Upvotes: 3
Reputation: 1065
You can run scala -Xprint:parser -e "val (a, b) = (1, 2)"
to desugar the code. What actually happened is:
val x$1 = (1, 2) match {
case Tuple2((a @ _), (b @ _)) => Tuple2(a, b)
}
val a = x$1._1
val b = x$1._2
Upvotes: 2
Reputation: 2345
val defines a variable that cannot be reassigned. Then the (a, b, ..)
notation exposes a tuple with values a, b, ... to be assigned.
Here's an example you can run:
// define types
type A = String
type B = String
type C = String
type D = String
// adding tuple@ to show a,b,c,d are components of a tuple aka extraction
val tuple@(a: A, b: B, c:C, d:D) = {
("aString", "bString", "cString", "dString")
}
println(tuple)
Additionally, you can specify types more explicitly such as
val tuple@(a: A, b: B, c:C, d:D): (A, B, C, D) = {
("aString": A, "bString": B, "cString": C, "dString": D)
}
And the output is:
defined type alias A
defined type alias B
defined type alias C
defined type alias D
tuple: (A, B, C, D) = (aString,bString,cString,dString)
a: A = aString
b: B = bString
c: C = cString
d: D = dString
(aString,bString,cString,dString)
Upvotes: 2