Scala duck

I have a case class, for example:

// parent class sealed abstract class Exp() // the case classes I want to match have compatible constructors case class A (a : Exp, b : Exp) extends Exp case class B (a : Exp, b : Exp) extends Exp case class C (a : Exp, b : Exp) extends Exp // there are other case classes extending Exp that have incompatible constructor, eg // case class D (a : Exp) extends Exp // case class E () extends Exp // I don't want to match them 

I want to combine:

 var n : Exp = ... n match { ... case e @ A (a, b) => foo(e, a) foo(e, b) case e @ B (a, b) => foo(e, a) foo(e, b) case e @ C (a, b) => foo(e, a) foo(e, b) ... } def foo(e : Exp, abc : Exp) { ... } 

Is there a way to combine these three cases into one case (without adding an intermediate parent class to A, B, C)? I cannot change the definition of A, B, C or Exp. Something like:

 var n : Exp = ... n match { ... case e @ (A | B | C) (a, b) => // invalid syntax foo(e, a) foo(e, b) ... } 

which obviously does not work, and do not:

 var n : Exp = ... n match { ... case e @ (A (a, b) | B (a, b) | C (a, b)) => // type error foo(e, a) foo(e, b) ... } 
+8
scala pattern-matching case-class
source share
1 answer

While the following “solution” is just another way of writing what you already have, it can help if you need to use the same match in multiple places and avoid code duplication.

The following custom unapply:

 object ExpABC { def unapply(e:Exp):Option[(Int, Int)] = e match { case A(a, b) => Some(a, b) case B(a, b) => Some(a, b) case C(a, b) => Some(a, b) case _ => None } } 

lets you write

 n match { case e @ ExpABC(a, b) => println(e) println(a) println(b) } 

Thus, you do not need to modify the source classes at all. I don't know how best to do this, which does not include modifying the A / B / C classes, but I really want to learn @Stackoverflow;)

+11
source share

All Articles