SLN
SLN

Reputation: 5092

Scala pattern matching for tuple with options still needs unwrapping for the some case

f(Int) is an function that returns an Option[Int].

def findIntPair(x: Int, y: Int): (Int, Int) = {
    (f(x), f(y)) match {
      case (None, None) || (None, _) || (_, None)  => fail("Unable to find the pair" )
      case (a, b) => (a.get, b.get) // why I still need to unwrap by get
    } 
}

Why does the last case(a, b) not unwrap them into Int but still keep them as Option[Int]?

FYI: I'm using intelliJ IDEA.

Upvotes: 1

Views: 298

Answers (4)

Med Ali
Med Ali

Reputation: 141

I think the right solution is that you do that by this way:

   (f(x), f(y)) match {
     case (None, None) | (None, _) | (_, None)  => fail("Unable to find the pair" )
     case (Some(a), Some(b)) => (a, b) 
   }
 }

Upvotes: 1

Tim
Tim

Reputation: 27431

Here is an alternative way of expressing this logic:

def findIntPair(x: Int, y: Int): Option[(Int, Int)] =
  for {
    a <- f(x)
    b <- f(y)
  } yield (a,b)

This has the advantage that it will not compute f(y) if f(x) returns None. This version returns an Option so that the error can be processed later, but you can process it inside the function like this:

def findIntPair(x: Int, y: Int): (Int, Int) =
  (
    for {
      a <- f(x)
      b <- f(y)
    } yield  (a, b)
  ).getOrElse(fail("Unable to find the pair"))

Note that this assumes that fail returns (Int, Int), which is what would be necessary for the code in the question to work.

Upvotes: 0

Pedro Correia Luis
Pedro Correia Luis

Reputation: 1095

Thats because:

def findIntPair(x: Int, y: Int): (Int, Int) = {
    (f(x), f(y)) match {
      case (None, None) || (None, _) || (_, None)  => fail("Unable to find the pair" )
      case (a, b) => (a.get, b.get) //here f(x) = a and f(y) = b
    } 
}

You want something like this:

def findIntPair(x: Int, y: Int): (Int, Int) = {
(f(x), f(y)) match {
  case (None, None) || (None, _) || (_, None)  => fail("Unable to find the pair" )
  case (Some(a), Some(b)) => (a, b)
} 

}

But thats not the best way to do that i think this is better:

def findIntPair(x: Int, y: Int): (Int, Int) = {

    if(f(x).isDefined && f(y).isDefined) (f(x).get,f(y).get)
    else fail("Unable to find the pair" )

}

Upvotes: 0

Shaido
Shaido

Reputation: 28422

You need to pattern match with Some:

def findIntPair(x: Int, y: Int): (Int, Int) = {
    (f(x), f(y)) match {
      case (None, None) || (None, _) || (_, None)  => fail("Unable to find the pair" )
      case (Some(a), Some(b)) => (a, b)
    } 
}

A bit cleaner using a catch-all case _:

def findIntPair(x: Int, y: Int): (Int, Int) = {
    (f(x), f(y)) match {
      case (Some(a), Some(b)) => (a, b)
      case _  => fail("Unable to find the pair" )
    } 
}

Upvotes: 4

Related Questions