Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple assignment of non-tuples in scala

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" to x and 1 to y.

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 a Tuple2 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?

like image 743
Elazar Leibovich Avatar asked Mar 04 '10 18:03

Elazar Leibovich


2 Answers

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

like image 94
Randall Schulz Avatar answered Sep 23 '22 21:09

Randall Schulz


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(" ") 
like image 41
Dario Avatar answered Sep 22 '22 21:09

Dario