2

I have this line of code, where I use the most idiomatic way I know, for destructuring an object coming back from a function:

val (a, b) = foo match { case MyObjectType(a, b) => (a, b) }

The object's prototype being:

case class MyObjectType(Type1: SomeType1, Type2: SomeType2)

Of course I could otherwise:

val returnType = foo
val (a, b) = (returnType.a, returnType.b)

But the latter is rather a different form of stating the same problem - this is really not elegant. Could a Scala macro come to the rescue to provide a succinct idiom? perhaps allowing syntax like either:

val (a, b) = foo deconstruct { MyObjectType(a, b) => (a, b) } // merely more shorthand, like scala allows e.g. within a map block

val (a, b) = tuplize(foo)                                     // assumes tuplize can iterate the vals of MyObjectType

tupleResult(a, b) = foo                                       // radical macro api exploring the limits of macro safety...

tupledVars(foo)                                               // macro extreme
matanster
  • 15,072
  • 19
  • 88
  • 167

2 Answers2

10

Kind of an answer, but that does not give you a tuple. Do you know that this works:

val MyObjectType(a,b) = foo

Also if you are destructuring varargs T* you can do Code such as follows:

val Array(first, second, _*) = Array(1,2,3,4)
val Array(fst, snd, _*) = Array(1,2)

If you want tuples directly see In Scala, is there an easy way to convert a case class into a tuple?

Community
  • 1
  • 1
uberwach
  • 1,119
  • 7
  • 14
  • Thanks this is better than a tuple, I was thinking tuple just because I thought the solution would go through one, but this gets the job done! I wonder how that works under the hood though... the referenced answer had really poor answers on it BTW. This solution is much more useful, yet I wonder why it works, if you'd care to elabroate. – matanster Mar 09 '15 at 11:50
0

You may wish to explore generic programming with Shapeless

scala> import shapeless._, syntax.std.product._, syntax.std.tuple._
import shapeless._
import syntax.std.product._
import syntax.std.tuple._

scala> case class Foo(i: Int, s: String, b: Boolean)
defined class Foo

scala> val foo = Foo(1, "foo", true)
foo: Foo = Foo(1,foo,true)

Now with the help of Generic we can convert Foo to HList and back

scala> Generic[Foo].to(foo)
res0: shapeless.::[Int,shapeless.::[String,shapeless.::[Boolean,shapeless.HNil]]] = 1 :: foo :: true :: HNil

scala> Generic[Foo].from(res0)
res1: Foo = Foo(1,foo,true)

Or you can use nice syntactic sugar provided by syntax.std.product

scala> foo.toHList
res2: this.Repr = 1 :: foo :: true :: HNil

scala> foo.toTuple
res3: (Int, String, Boolean) = (1,foo,true)

See feature overview and examples for more information.

4e6
  • 10,696
  • 4
  • 52
  • 62
  • Thanks, but I keep an arm's length from mixing in shapeless for now, until I get better at understanding what it does under the hood and in particular the performance impacts of its idioms – matanster Mar 09 '15 at 11:44