1
votes

Am trying to implicitly deconstruct a class instance into a tuple to create a nicer DSL syntax.

Here's a simplified example of what I'm trying to do:

class Pair[A,B](a: A, b: B){
  def left = a
  def right = b
}
val pair = new Pair(1,2)
implicit def unpair[T1 <: Int, T2 <: Int](p: Pair[T1,T2]) = {
  (p.left, p.right)
}
val(a,b) = pair

results in:

error: constructor cannot be instantiated to expected type;
 found   : (T1, T2)
 required: Pair[Int,Int]

I know I can define a companion object with unapply method and manually handle the deconstruction (or call above implicit explicitly), but that makes for unwanted boilerplate.

Edit Ok, just to provide a bit more context, Pair is embedded within an instance that implements map, flatMap, and withFilter (i.e. to be used within for comprehensions). So, desired usage looks something like:

val q = for{
  (a,b) <- tableA join tableB on(...)
  (c,d) <- tableC leftJoin tableD on(...)
  ....
} yield(a,b,c,d,...)

What I'd like to avoid is making Pair a case class (or adding a custom companion object to existing Pair class) and having to Pair(a,b) <- tableA join tableB on(...) everytime I join tables (read: often)

Original

Is there a way to pull this off in Scala 2.10 or 2.11?? There are some older SO threads from 2.8/2.9 days that indicate this functionality is not possible, but am hoping things have changed since then, or that there's a workaround available.

2

2 Answers

2
votes

You need to set type of a and b explicit:

 val(a,b): (Int, Int) = pair
1
votes

If you just want to extract left and right (I'm guessing from your example), why not to solve your problem with even less code:

case class Pair[A, B](left: A, right: B)

val pair = Pair(1, 2)

val Pair(a, b) = pair

println(a, b)