0

Hi I have code like below:


def something(input1: Int, input2: Int): Try[Int] = {
  if (input1 == 0) {
     Failure(new RuntimeException("input1 should not be 0"))
  }
  if (input2 == 0) {
     Failure(new RuntimeException("input2 should not be 0"))
  }
  Success(input2)
}

and I am trying to use the above function like this way: something(0, 1) i am expecting the above should return a Failure, but it actually not, it execute the Failure() statement but it still execute the following code block after the failure if I want to exit this function with the first Failure, how to achieve it? (I know I can do if else if block to avoid executing the following code block but I don't want to do that, assuming there are a lot of checks)

heheda
  • 61
  • 1
  • 7
  • looks like if i do return Failure(new RuntimeException("input1 should not be 0")) it is going to exit the function – heheda Nov 19 '19 at 03:39
  • 1
    Use `else if`. There's no good reason not to. – jwvh Nov 19 '19 at 04:02
  • As mentioned by fenixil, in **Scala** expressions return values, and the return value of a block is its last expression. Thus, You just need to `if (...) { ... } else if (...) { ...} else { ... }` To creaste just one big if expression. - Also, if the body of each block is just one expression _(like in your case, you may just remove the braces)_ - also since your entire method is just one expression _(an if expression)_ then you may also remove those brackets and just leave the if structure. – Luis Miguel Mejía Suárez Nov 19 '19 at 04:08

2 Answers2

1

Scala does have return but it's just highly discouraged(thanks to @jwvh for correction). Scala implies that any statement can return something. In your example by writing Failure() inside if means that if statement return it. As you don't assign it anywhere, it is just ignored. You program looks something like below from compiler perspective (it will not compile, I just want to demonstrate what actually happens):

def something(input1: Int, input2: Int): Try[Int] = {
  val ifVal1 = if (input1 == 0) {
     Failure(new RuntimeException("input1 should not be 0"))
  }
  val ifVal2 = if (input2 == 0) {
     Failure(new RuntimeException("input2 should not be 0"))
  }
  val res = Success(input2)
  res
}

If you need many checks, then pattern matching is your friend:

def something(input1: Int, input2: Int): Try[Int] = 
  (input1, input2) match {
    case (0, _) => Failure(new RuntimeException("input1 should not be 0"))
    case (_, 0) => Failure(new RuntimeException("input2 should not be 0"))
    case _ => Success(input2)
  }
fenixil
  • 2,106
  • 7
  • 13
  • i did not get your first example, you assign the if block to ifVal1.ifVal2, but it still won't exit the function at the first Failure if first if condition meets, ifVal1 now is equal to Failure(), how can I just return the failure from there? – heheda Nov 19 '19 at 04:21
  • you may put 5 checks or [more](https://github.com/apache/spark/blob/882f54b0a323fb5cd827d600b3c3332e1fcdf65a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/literals.scala#L56) unless your code is readable. – fenixil Nov 19 '19 at 04:24
  • @heheda, with first example I demonstrated how your code looks like from compiler perspective - you returning the values from if statements and they are just ignored. Please read the thread that I left in my comment. Pattern matching is a canonical way of handling many conditions in scala, I'd strongly recommend to use it instead of imperative `return` clause. Perhaps I don't follow your concerns so feel free to elaborate. – fenixil Nov 19 '19 at 04:39
0

You just need to chain your conditions with else clauses:

def something(input1: Int, input2: Int): Try[Int] =
  if (input1 == 0) {
    Failure(new RuntimeException("input1 should not be 0"))
  } else if (input2 == 0) {
    Failure(new RuntimeException("input2 should not be 0"))
  } else {
    Success(input2)
  }
Tim
  • 26,753
  • 2
  • 16
  • 29