I have a sealed trait with various case class implementations. I want to pattern match on multiple classes at once for the same match expression. I can't seem to do it without decomposing the case classes and "|" between them
currently looks like:
sealed trait MyTrait {
val param1: String
...
val param100: String
}
case class FirstCase(param1: String ...... param100: String) extends MyTrait
...
case class NthCase(param1: String ..... param100: String) extends MyTrait
another place in code:
def myFunction(something: MyTrait) = {
...
val matchedThing = something match {
// this doesn't work with "|" character
case thing: FirstCase | SecondCase => thing.param1
...
case thing: XthCase | JthCase => thing.param10
}
}
Let's go there step by step:
The |
operator, in the context of pattern matching, allows you to define alternative patterns, in the following form:
pattern1 | pattern2
If you want to define a pattern that matches a type, the pattern must be provided in the following form:
binding: Type
Providing a choice between two different types should then be provided in the following form:
binding1: Type1 | binding2: Type2
To bind a single name to the two alternative bindings you can discard the name of the individual bindings (using the _
wildcard) and bind the name of the overall pattern to another binding using the @
operator, as expressed in the following example:
binding @ (_ : Type1 | _ : Type2)
The following is an example:
sealed trait Trait {
def a: String
def b: String
}
final case class C1(a: String, b: String) extends Trait
final case class C2(a: String, b: String) extends Trait
final case class C3(a: String, b: String) extends Trait
object Trait {
def f(t: Trait): String =
t match {
case x @ (_ : C1 | _ : C2) => x.a // the line you are probably interested in
case y: C3 => y.b
}
}
Here is some sample output on invoking f
:
scala> Trait.f(C1("hello", "world"))
res0: String = hello
scala> Trait.f(C2("hello", "world"))
res1: String = hello
scala> Trait.f(C3("hello", "world"))
res2: String = world
You can play around with the presented examples here on Scastie.
This worked for me https://scastie.scala-lang.org/pT4euWh6TFukqiuPr4T6GA:
sealed trait Sup {
def a: String
def i: Int
}
case class First(a: String, i: Int, d: Double) extends Sup
case class Second(a: String, i: Int, x: Seq[Double]) extends Sup
case class Third(a: String, i: Int, c: Char) extends Sup
val sups = Seq(First("s", 1, 1.0), Second("s", 4, Seq(1.1)), Third("s", 4, 'f'))
sups.foreach {
case _: First | _: Second => println("ffff")
case _ => println("ggg")
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With