How to pattern match large Scala case classes?

前端 未结 4 2032
攒了一身酷
攒了一身酷 2020-12-05 01:43

Consider the following Scala case class:

case class WideLoad(a: String, b: Int, c: Float, d: ActorRef, e: Date)

Pattern matching allows me

相关标签:
4条回答
  • 2020-12-05 02:22

    I don't know if this is appropriate, but you can also build an object just to match that field, or that set of fields (untested code):

    object WideLoadActorRef {
      def unapply(wl: WideLoad): Option[ActorRef] = { Some(wl.d) }
    }
    
    someVal match {
      case WideLoadActorRef(d) => d ! someMessage
    }
    

    or even

    object WideLoadBnD {
      def unapplySeq(wl: WideLoad): Option[(Int,ActorRef)] = { Some((wl.b,wl.d)) }
    }
    
    someVal match {
      case WideLoadBnD(b, d) => d ! SomeMessage(b)
    }
    
    0 讨论(0)
  • 2020-12-05 02:24

    You can always fall back to guards. It's not really nice, but better than normal pattern matching for you monster case classes :-P

    case class Foo(a:Int, b:Int, c:String, d:java.util.Date)
    
    def f(foo:Foo) = foo match {
      case fo:Foo if fo.c == "X" => println("found")
      case _ => println("arrgh!")
    }
    
    f(Foo(1,2,"C",new java.util.Date())) //--> arrgh!
    f(Foo(1,2,"X",new java.util.Date())) //--> found
    

    That said I think you should rethink your design. Probably you can logically group some parameters together using case classes, tuples, lists, sets or maps. Scala does support nested pattern matching:

    case class Bar(a: Int, b:String)
    case class Baz(c:java.util.Date, d:String)
    case class Foo(bar:Bar, baz:Baz)
    
    def f(foo:Foo) = foo match {
       case Foo(Bar(1,_),Baz(_,"X")) => println("found")
       case _ => println("arrgh!")
    }
    
    f(Foo(Bar(1,"c"),Baz(new java.util.Date, "X"))) //--> found
    f(Foo(Bar(1,"c"),Baz(new java.util.Date, "Y"))) //--> arrgh! 
    
    0 讨论(0)
  • 2020-12-05 02:41

    You can create a new case class which is a summary of your larger case class

    case class WideLoad(a: String, b: Int, c: Float, d: ActorRef, e: Date)
    case class WideLoadSummary(d: ActorRef, e: Date)
    

    And then pattern match as normal.

    val someVal = WideLoadSummary(wideload.d, wideload.e)
    
    someVal match {
        case WideLoadSummary(d, _) => d ! SomeMessage(...)
    }
    
    0 讨论(0)
  • 2020-12-05 02:47

    You can just specify the type in the matched pattern:

    case class WideLoad(a: String, b: Int, c: Float, d: ActorRef, e: Date)
    
    val someVal = WideLoad(...)
    
    someVal match {
        case w: WideLoad => w.d ! SomeMessage(...)
    }
    
    0 讨论(0)
提交回复
热议问题