Multiple assignment of non-tuples in scala
Solution 1
All you need to do is make your val side (left of the =
) compatible with your initializer (right of the =
):
scala> val Array(x, y, z) = "XXX,YYY,ZZZ".split(",")
x: java.lang.String = XXX
y: java.lang.String = YYY
z: java.lang.String = ZZZ
As you expected, a scala.MatchError
will be thrown at runtime if the array size don't match (isn't 3, in the above example).
Solution 2
Since your string can have arbitrary contents, the result cannot be guaranteed to have a 2-tuple-form by the type-system (and no conversion would make sense at all). Therefore you'll have to deal with sequences (like arrays) anyway.
Thankfully there are right-ignoring sequence patterns which allow you to match the result values conveniently nevertheless.
val Seq(x, y, _ @ _*) = "a b".split(" ")
Solution 3
scala> val Array(x, y, _*) = "a b" split " " x: java.lang.String = a y: java.lang.String = b
Elazar Leibovich
Updated on June 06, 2022Comments
-
Elazar Leibovich almost 2 years
Just to clarify, when I say multiple assigment, parallel assignment, destructuring bind I mean the following pattern matching gem
scala> val (x,y) = Tuple2("one",1) x: java.lang.String = one y: Int = 1
which assigns
"one"
tox
and1
toy
.I was trying to do
val (x,y) = "a b".split()
I was expecting that scala would attempt to pattern match the array with the pattern, and would throw a runtime exception if the length of the array wouldn't match the length of the pattern.
All my attempts to easily convert an
Array
to aTuple2
were futile.scala> Tuple2(Array(1,2):_*) <console>:7: error: wrong number of arguments for method apply: (T1,T2)(T1, T2) in object Tuple2 Tuple2(Array(1,2):_*) ^ scala> Tuple2(Array(1,2).toList:_*) <console>:7: error: wrong number of arguments for method apply: (T1,T2)(T1, T2) in object Tuple2 Tuple2(Array(1,2).toList:_*)
Is there any neat way to use multiple assignment with arrays or lists?
-
Elazar Leibovich about 14 yearsQuoting myself: "I was expecting that scala would attempt to pattern match the array with the pattern, and would throw a runtime exception if the length of the array wouldn't match the length of the pattern", also see Randall's solution. Anyway this is a nice one as well. So simple I wish I thought about it myself. +1.
-
Randall Schulz about 14 yearsIn Scala 2.8, Array is no longer Seq, so this technique doesn't work there.
-
retronym about 14 yearsThis works because the object
Array
includes theunapplySeq
method, making it usable as an Exractor Pattern.Array.unapplySeq("XXX,YYY,ZZZ".split(",")
is called, returningSome(ArrayBuffer(XXX, YYY, ZZZ))
, which is aSome
, and contains three elements to bind tox
,y
, andz
. -
psp about 14 yearsThe technique certainly works, you just write "Array" instead of "Seq". Or if you can be chill about the end of the String, val Array(x, y) = "a b" split " " take 2
-
Blaisorblade about 12 years
val Array(x, y, _*) = "a b".split(" ")
also works with less syntactic clutter. I don't think that_ @
is ever useful. -
Batato almost 6 yearswhy
val Array(X, Y, Z) = "XXX,YYY,ZZZ".split(",")
doesn't work? I get<console>:14: error: not found: value X...
-
Jim Balter almost 5 years@Batato match variables must be lowercase