Matching patterns for classes with a large / long case

Is there a more readable and more reliable (for refactoring) way to match case classes like this?

Example

Hull class

A very long random class with many "fields".

case class Data(name: String, time: Long, ..., userId: Option[UUID] ..., orders: Int, ... ) //more fields fields more 

Matching Pattern: Option a

Works. But an error occurred while changing the position of the field. One ends with a count of _ .

 res match { case data@Data (_,_,_,_,_,_,Some(id),_,_,_,6,_,_) => (id, data.orders) case _ => ... } 

Matching Pattern: Option B

It also works. It is stable for changing orders. It turns out very cumbersome, with a lot of checks in the guard. It is also necessary to repeat the reading of the value.

 res match { case data: Data if data.userId.isDefined && data.orders == 6 => (data.userId.get,data.orders) case _ => ... } 

Rephrased question

Is there a way to combine Options A and B to benefit from both approaches?

+6
source share
2 answers

You can use a custom extractor:

 res match { case ExtractUserIdAndOrders(Some(id), 6) => ... case _ => ... } 

Where

 object ExtractUserIdAndOrders { def unapply(data: Data) = Some((data.userId, data.orders)) } 

You can define it inside the method if you need it only once or in a wider area for several similar matches.

+10
source

As long as there is an unapply method in the area that takes a parameter from the type with which you are comparing, you can define a custom extractor for this, for example.

 case class Big(foo: String, bar: String, baz: Option[String], x: Int, y: Int) object SmallerBig { def unapply(x: Big): Option[(Option[String], Int)] = Some(x.baz, xy) } val x = Big("a", "b", Some("c"), 1, 2) x match { case Big(_, _, _, _, _) => case SmallerBig(Some(a), b) => } 

The return type of the unapply method should not be Option , but the return type must contain the get and isDefined methods.

+2
source

All Articles