1

Say I have the following

case class IntWrap(value:Int)

I would like to extract the same variable from two cases as follows:

x match {
  case value:Int | IntWrap(value) => dosomethingwith(x)
  case _ => ???
}

but the only way I have been able to do this is as:

x match {
  case value:Int => dosomethingwith(x)
  case IntWrap(value) => dosomethingwith(x)
  case _ => ???
}

Is there a better way, as in my real life case dosomething is actually a large block of code which is not so easy to encapsulate.

1
  • Remember that functions can be nested, so if dosomething "is not so easy to encapsulate" because it uses local variables or parameters of the method, you can define it just before the match and access the same variables. Commented May 30, 2013 at 11:59

3 Answers 3

2

If it is really the case that you want to do something with x, not with the extracted value, then the following would work:

case class IntWrap(value:Int) // extends T

def dosomethingwith(x: Any) = x

val x: Any = IntWrap(101)

x match {
  case _: Int | _: IntWrap => dosomethingwith(x)
  case _ => ???
}


If you actually want to work with the extracted value, you could factor out the corresponding match block into its own extractor and reuse that wherever necessary:

x match {
  case Unwrap(value) => dosomethingwith(value)
  case _ => ???
}

object Unwrap {
  def unapply(x: Any) = x match {
    case x: Int => Some((x))
    case IntWrap(value) => Some((value))
    case _ => None
  }
}
Sign up to request clarification or add additional context in comments.

Comments

0

I honestly don't see an issue with the way you are doing things. As long as dosomethingwith is a separate function then I don't see any issues with duplicate code. If your code looked like this then I don't see any need to come up with other solutions:

def foo(x:Any){
  x match {
    case value:Int => dosomethingwith(value)
    case IntWrap(value) => dosomethingwith(value)
    case _ => ???
  }
}

def dosomethingwith(x:Int){
  //do something complicated here...
}

Comments

0

I came up with sth a little bit different, but it may help you avoid duplicates:

  case class IntWrap(value: Int)
  implicit def intWrapToInt(intWrap: IntWrap) = intWrap.value

  def matchInt(x: AnyVal) = x match {
    case i: Int => println("int or intWrap")
    case _ => println("other")
  }

  //test
  matchInt(IntWrap(12))          //prints int or intWrap
  matchInt(12)                   //prints int or intWrap
  matchInt("abc")                //prints other

It won't work for every reference, though. So, be careful.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.