I have a match case with if
and the expression is always the same.
I put some pseudo code:
value match {
case A => same expression
case B(_) if condition1 => same expression
case _ if condition2 => same expression
...
case _ => different expression //similar to an else
}
The match contains both case object
(case A
) matching and case class
(case B(_)
)
Is it the best practice?
CodePudding user response:
Try to explain this code in words. "This function returns one of two values. The first is returned if the input is A
. Or if the input is of type B
and a condition holds. Oh, or if a different condition holds. Otherwise, it's the other value". That sounds incredibly complex to me.
I have to recommend breaking this down at least a bit. At minimum, you've got two target expressions, and which one is chosen depends on some predicate of value
. That sounds like a Boolean
to me. Assuming value
is of some trait type Foo
(which A.type
and B
extend), you could write
sealed trait Foo {
def isFrobnicated: Boolean = this match {
case A => true
case B(_) if condition1 => true
case _ => condition2
}
}
...
if (value.isFrobnicated) {
same expression
} else {
different expression
}
Now the cognitive load is split into two different, smaller chunks of code to digest, and presumably isFrobnicated
will be given a self-documenting name and a chunk of comments explaining why this distinction is important. Anyone reading the bottom snippet can simply understand "Oh, there's two options, based on the frobnication status", and if they want more details, there's some lovely prose they can go read in the isFrobnicated
docs. And all of the complexity of "A
or B
if this or anything if that" is thrown into its own function, separate from everything else.
If A
and B
don't have a common supertype that you control, then you can always write a standalone function, an implicit
class, or (if you're in Scala 3) a proper extension method. Take your pick.
Depending on your actual use case, there may be more that can be done, but this should be a start.
CodePudding user response:
It's not common to mix in case objects with case classes in the same pattern match. You should analyze if one could be converted into the other, to have the same thing. Either you match case objects or case classes.
You should not have 2 case _
clauses in a pattern match. If your condition is not dependent on the case
clause there is no point in having case _ if condition2 => same expression
You should keep one, and move the if
after the arrow symbol :
value match {
case A => same expression
case B(_) if condition1 => same expression
...
case _ =>
if condition2
same expression
else
different expression //similar to an else
}