Lots of nested matches ... case in match pattern

I have an automatically created client for a web service. I have many complex classes, and I have to do a mapping with it. At the moment, I have a structure that looks like this:

val response = client.getResponse response match { case Left(_) => None case Right(a: SomeClass) => a match { case SomeClass2(b: Option[SomeClass3]) => b match { case None => None case Some(c: SomeClass3) => c match { case SomeClass4(_, _, _, _, d: Seq[SomeClass4]) => d match { case Nil => None case seq: Seq[SomeClass5] => seq match { case Nil => None case Seq( xs@ _*) => xs map { x => x match { case Nil => None case SomeClass6(e: SomeClass7) => e match { case Nil => None case SomeClass8(f, _, _, _, _) => f match { case Nil => None case Seq( xs@ _*) => xs map { x => x match { case Nil => None case SomeClass9(g: Seq[SomeClass9], _, _, _, _, _, _, _, _, _, _) => /* + some nested levels more*/ } } } } } } } } } } } 

where SomeClass1 - SomeClass9 - case classes.

As you can see, this seems intimidating. What should I do with this? What is the standard way to do this better?

I assume that there should be not only refactoring, but also a different approach.

+4
source share
3 answers

Assuming a should be SomeClass2 , but not SomeClass (same with b , c , d ).

You can use alternative patterns such as case A | B => ... case A | B => ... and structural patterns, for example Some(MyClass(f)) .

You can also use the partial function in map as map { case ... } instead of map { x => x match {...} } .

And I think there is an error in your code: there is a check for case Nil => ...; case SomeClass8(...) => ... case Nil => ...; case SomeClass8(...) => ...

You can replace Seq(xs @_*) with xs . If you need a whole collection, you do not need to retrieve the elements.

Your code:

 response match { case Left(_) | Right(SomeClass2(None)) | Right(SomeClass2(Some(SomeClass3(_, _, _, _, Nil))) => None case Right(SomeClass2(Some(SomeClass3(_, _, _, _, xs))) => xs map { case SomeClass6(None) | SomeClass6(Some(SomeClass8(Nil, _, _, _, _))) => None case SomeClass6(Some(SomeClass8(xs, _, _, _, _))) => xs map { case Nil => None case SomeClass9(g, _, _, _, _, _, _, _, _, _, _) => /* + some nested levels more*/ } } } 

You should also retrieve nested matches for individual methods.

Matching patterns is not the only solution. You can use the Either and Option methods:

 response.right.toOption.collect { // No need for the first part. case SomeClass2(Some(SomeClass3(_, _, _, _, xs)) if xs.nonEmpty => ... } 
+4
source

You may find the extractors useful. It may also be worth smoothing out some of the cases, so you have

 case Right(SomeClass(SomeClass2(Some(SomeClass3(value))))) => value ... case _ => None 

instead of having a None case explicitly defined at each level.

+5
source

You can probably reduce this complexity by using for understanding, not for pattern matching.

One simple possibility is matching the sequence with another pattern match:

 case seq: Seq[SomeClass5] => seq match { case Nil => None case Seq( xs@ _*) => xs map { x => x match { ... } } } 

This is very ugly because you used match to eliminate the Nil case and then match seq again. Two match levels for working with one object. It can become

 case seq: Seq[SomeClass5] => for (x <- seq) yield { x match { ... } } 

This removes the Nil check check and removes several levels of nesting, which is a big win. And you do it in at least two layers to get an even greater victory. Of course, this returns a sequence (possibly Nil ), not f(x) or None , but you can easily convert it. One way to do this without adding another nesting would be as follows:

 case seq: Seq[SomeClass5] => (for (x <- seq) yield { x match { ... } }) match { case Nil => None case Seq(i) => Some(i) case ... } 

Or, if (as I suspect), you expect that in these sequences there will be only one element in them ...

 case seq: Seq[SomeClass5] => (for (x <- seq) yield { x match { ... } }) match { case Seq(i) => Some(i) case _ => None } 
+2
source

Source: https://habr.com/ru/post/1502533/


All Articles