Search code examples
scalapattern-matching

How to extract the matching object with 1 operation in Scala?


I have the following piece of code:

foo collectFirst {
  case x if check(expensive(x)) => do_something(expensive(x))
  case x if check2(expensive2(x)) => do_something_else(expensive2(x))
}  

To prevent expensive() being called twice, I can do this:

object expensive_helper {
  def unapply[A, B](x: A): Option[B] =
    ???
}

But, this is pretty verbose. Is there a better way?


Solution

  • I have this helper in my common utils:

    case class matches[A, B](f: A => B)(check: B => Boolean) {
      def unapply(a: A): Option[B] = Option(f(a)).filter(check)
    }
    

    Here's how to use it:

    val x      = "abcd"
    val base64Url = matches((s: String) => Try(Base64.urlDecode(s))
    (_.isSuccess)
    val base64 = matches((s: String) => Try(Base64.decode(s))
    (_.isSuccess)
    
    x match {
      case base64Url(y) => println("Decoded URL =" + y)
      case base64(y)    => println("Decoded     =" + y)
      case _            => println("Could not decode " + x)
    }