Here is the basic case that is shown in so many examples:
scala> val (x,y) = (10, "ten")
x: Int = 10
y: java.lang.String = ten
In this example the Tuple (10,"ten") is assigned to x and y using the same mechanism that match and case uses.
scala> (10, "ten") match {
| case (x,y) => println(x,y)
| }
(10,ten)
I finally came to the realization that if we can do this with Tuples can we not do it with other case classes or classes with Extractors?
scala> case class T(one:Int, two:String)
defined class T
scala> val t = T(6,"six")
t: T = T(6,six)
scala> val T(i,j) = t
i: Int = 6
j: String = six
scala> val T(a,b) = T(10,"book")
a: Int = 10
b: String = book
Some may ask: "Why do you need this if you can use Tuples?" My answer is that Tuples while handy have no semantic meaning. A case class can have meaning. So it is better to pass around an object with meaning rather than a Tuple.
Consider the case where a method returns a case class, one could use this method to extract just the values desired or extract them into local variables:
scala> val T(a,_) = T(10,"book")Pretty cool eh!
a: Int = 10
Now in the spirit of "how deep down the rabbit hole can we go":
scala> object Names{
| def unapply(s:String): Option[String] = {
| if( s.trim.startsWith("Mr")) Some(s.trim.drop(2))
| else None
| }
| }
defined module Names
scala> val Names(name) = "Mr Jones"
name: String = Jones
Wow so extractors also work. This is too much fun :)
3 comments:
Oh, wow. This is quite awesome! I must commit this to memory for my bag of tricks. Thank you.
While wicked cool, this doesn't really count as multiple assignment, but rather as a lovely syntax for multiple destructuring declaration. You can't reassign variables this way, either for tuples or the general extractor case. This
var x = 3
var y = 5
(x, y) = (42, 43)
is invalid
You write that tuples has no semantic meaning, I don't agree with this. The element types define the semantic meaning of a tuple. For example, you can emulate a case class by using the first tuple element to distinguish class:
scala> object A
defined module A
scala> (A, 1) == (A, 1)
res10: Boolean = true
scala> (A, 1) == (A, 2)
res11: Boolean = false
scala> object B
defined module B
scala> (A, 1) == (B, 1)
res12: Boolean = false
Post a Comment