Andreas Neumann Andreas Neumann - 3 months ago 11
Scala Question

Pattern matching on big/long case classes

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

Example



Case Class



Very long case class with many "fields".

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


Pattern match: Variant a



Works. But error prone when fields position changes. One ends up counting
_
.

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

}


Pattern match: Variant b



Works also. Is stable to changing orders. Gets really cumbersome with more checks in the guard. Also reading the value has to be repeated.

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


Question rephrased



Is there a way to combine Variant A and B to get the benefit of both approaches ?

Answer

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 just once, or in a wider scope for multiple similar matches.

Comments