Home > Back-end >  Pass argument with multiple return points
Pass argument with multiple return points

Time:07-04

Assuming I have a function example() that has a parameter param: Int?. I would like to call it so that the argument can be passed with certain conditionals.

To try to explain better, let's define the example() function:

fun example(prev: Int, param: Int?) = doSomething(prev, param)

So assuming that under certain conditions, the value passed as an argument can be null or any other value. Naturally, I would do something like this:

val param = if (x() > 100) null
            else if (x() < 0) 123
            else 456

example(123, param)

Another way to get this to work would be inline val like this:

example(123, if (x() > 100) null
             else if (x() < 0) 123
             else 456)

The problem is that I have a larger conditional in my real code and it ends up being very "visually accumulated". Both examples works, but I wanted to not using else or when under these conditions. It would be something like:

example(123, run {
    if (x() > 100)
        return null

    if (x() < 0)
        return 123

    return 456
})

However, the code above does not work as expected. The return points actually cause the entire flow of the function to return, and are not meant to return as the argument itself.

What I expect, in reality, would be something like the function below:

fun generateExampleArgument(): Int? {
    if (x() > 100)
        return null

    if (x() < 0)
        return 123

    return 456
}

// Then:
example(123, generateExampleArgument())

CodePudding user response:

In regard of readability and quote "... larger conditionals ..." the when clause is better than the if ... else if ... one:

example(
  123,
  when {
    x() > 100 -> null
    x() < 0   -> 123
    else      -> 456
  }
)

Another possibility is to use a function to pre-calculate the result for the second argument of example() or a lambda function, which moves the execution of that function into example() itself:

fun example(prev: Int, fn: (Int) -> Int?, x: Int) = doSomething(prev, fn(x))

val myLambda = { x: Int ->
 when {
   x > 100 -> null
   x < 0   -> 123
   else    -> 456
 }
}

example(120, myLambda, 111)

CodePudding user response:

After many attempts, I finally figured out how to solve it. My problem is that when using just return it actually instructs the return to the "larger function context", not on the argument itself, as expected.

The solution is to use run with return@run:

example(123, run {
    if (x() > 100)
        return@run null

    if (x() < 0)
        return@run 123

    456
})
  • Related