Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple return points in scala closure/anonymous function

As far as I understand it, there is no way in Scala to have multiple return points in an anonymous function, i.e.

someList.map((i) => {
    if (i%2 == 0) return i // the early return allows me to avoid the else clause
    doMoreStuffAndReturnSomething(i) // thing of this being a few more ifs and returns
})

raises an error: return outside method definition. (And if it weren’t to raise that, the code would not work as I’d like it to work.)

One workaround I could thing of would be the following

someList.map({
    def f(i: Int):Int = {
        if (i%2 == 0) return i
        doMoreStuffAndReturnSomething(i)
    }
    f
})

however, I’d like to know if there is another ‘accepted’ way of doing this. Maybe a possibility to go without a name for the inner function?

(A use case would be to emulate some valued continue construct inside the loop.)

Edit

Please believe me, that there is a need for avoiding the else statement, because, the doMoreStuff part might actually look like:

val j = someCalculation(i)
if (j == 0) return 8
val k = needForRecalculation(i)
if (k == j) return 9
finalRecalc(i)
...

which, when you only have an ifelse structure available gets easily messed up.

Of course, in the simple example I gave in the beginning, it is easier to just use else. Sorry, I thought this was clear.

like image 706
Debilski Avatar asked May 24 '10 17:05

Debilski


People also ask

How do you pass anonymous function in Scala?

We can define multiple arguments in the anonymous function. We are allowed to define an anonymous function without parameters. In Scala, We are allowed to pass an anonymous function as a parameter to another function. var myfun 1 = () => { "Welcome to GeeksforGeeks...!!" }

Are closures anonymous functions?

Anonymous functions, also known as closures , allow the creation of functions which have no specified name. They are most useful as the value of callable parameters, but they have many other uses. Anonymous functions are implemented using the Closure class.

What is the use of closure function in Scala?

A closure is a function, whose return value depends on the value of one or more variables declared outside this function. The following piece of code with anonymous function. There are two free variables in multiplier: i and factor.


3 Answers

If your anonymous function's that complex, I'd make it more explicit. Anonymous functions are not suited to anything more complex than a few lines. You could make it method private by declaring it within the using method

def myF(i:Int):Int = {
    if (i%2 == 0) return i
    doMoreStuffAndReturnSomething(i)
}
someList.map(myF(_))

This is a variation on your workaround, but is cleaner. They both keep it private to the local method scope.

like image 156
sblundy Avatar answered Oct 04 '22 08:10

sblundy


In your code comment, you wrote that you want to avoid the else keyword, but IMHO this does exactly what you want and its even two characters shorter ;-)

someList.map((i) => {
    if (i%2 == 0) i else
    doMoreStuffAndReturnSomething(i)
})
like image 25
Michel Krämer Avatar answered Oct 04 '22 09:10

Michel Krämer


The example you've given is easily solved by an if statement. There are no performance or other penalties for doing this.

But you might have some other situation, which looks roughly like

if (test) {
  if (anotherTest) {
    val a = someComputation()
    if (testOf(a)) return otherComputation()
  }
  else if (yetAnotherTest) return whatever()
}
bigComputation()

There are a few ways to deal with this sort of situation if you want to avoid the tangle of if-statements and/or code duplication needed to convert this to a form without returns.

There are various sneaky things you can do with Option or Either to keep state flowing along (with orElse and fold) so that you do only the computations you need to.

You're really better off creating a def as you suggest. But just to compare, consider an Option-wrapping style:

i => {
  ( if ((i%2)==0) Some(i) 
    else None
  ).getOrElse(doStuffAndReturn(i))
}

On the large example above, this style would give

( if (test) {
    if (anotherTest) {
      val a = someComputation()
      if (testOf(a)) Some(otherComputation()) else None
    }
    else if (yetAnotherTest) Some(whatever())
    else None
}).getOrElse(bigComputation())

Personally, I don't think it's clearer (and it's certainly not faster), but it is possible.

like image 42
Rex Kerr Avatar answered Oct 04 '22 10:10

Rex Kerr