Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala return statements in anonymous functions

Why does an explicit return statement (one that uses the return keyword) in an anonymous function return from the enclosing named function, and not just from the anonymous function itself?

E.g. the following program results in a type error:

def foo: String = {   ((x: Integer) => return x)   "foo" } 

I know it's recommended to avoid the return keyword, but I'm interested in why the explicit and implicit return statements have a different semantics in anonymous functions.

In the following example, the return statement "survives" after m has finished executing, and the program results in a run-time exception. If anonymous functions didn't return from the enclosing function, it would not be possible to compile that code.

def main(args: Array[String]) {   m(3) }  def m: (Integer => Unit) =   (x: Integer) => return (y: Integer) => 2 
like image 640
amaurremi Avatar asked Jul 19 '13 20:07

amaurremi


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...!!" }

Can we use return in scala?

The Scala programming language, much like Java, has the return keyword, but its use is highly discouraged as it can easily change the meaning of a program and make code hard to reason about.

What does => mean in scala?

=> is the "function arrow". It is used both in function type signatures as well as anonymous function terms. () => Unit is a shorthand for Function0[Unit] , which is the type of functions which take no arguments and return nothing useful (like void in other languages).

Are lambdas and anonymous functions the same?

Anonymous functions, lambda expressions, or function literals are all the same thing. Lambda (or \lambda) is the name given to anonymous functions in some languages like Python. These are functions not bound by an explicit identifier.


2 Answers

Formally speaking return is defined as always returning from the nearest enclosing named method

A return expression return e must occur inside the body of some enclosing named method or function. The innermost enclosing named method or function in a source program, f , must have an explicitly declared result type, and the type of e must conform to it. The return expression evaluates the expression e and returns its value as the result of f . The evaluation of any statements or expressions following the return expression is omitted.

So it doesn't have different semantics in a lambda. The wrinkle is that, unlike a normal method, a closure created from a lambda can escape a call to the enclosing method and you can get an exception if there is a return in such a closure.

If the return expression is itself part of an anonymous function, it is possible that the enclosing instance of f has already returned before the return expression is executed. In that case, the thrown scala.runtime.NonLocalReturnException will not be caught, and will propagate up the call stack.

Now, as for "why". One lesser reason is aesthetic: lambdas are expressions and it's nice when an expression and all its subexpression have the same meaning no matter what the nesting structure. Neal Gafter talks about that at http://gafter.blogspot.com/2006/08/tennents-correspondence-principle-and.html

The main reason it exists, though, is it allows you to easily simulate forms of control flow commonly used in imperative programming but still allows you to abstract things into higher order functions. As a toy example, Java's foreach construct (for (x : xs) { yada; }) allows a return inside the loop. Scala doesn't have a language level foreach. Instead, it puts foreach in the library (not counting "for expression" without yield since they just desugar to foreach). Having a non-local return means you can take a Java foreach and translate directly to a Scala foreach.

BTW, Ruby, Smalltalk, and Common Lisp (off the top of my head) also have similar "non-local" returns.

like image 128
James Iry Avatar answered Oct 21 '22 22:10

James Iry


The return keyword is reserved for (class) methods, it cannot be used in functions. You can easily test that:

object Foo {   val bar = (i: Int) => return i + i } 

This gives

<console>:42: error: return outside method definition        object Foo { val bar = (i: Int) => return i + i }                                           ^ 

Mostly you can treat methods and functions as the same, because of the function's apply method behaving syntactically like calling a method, and so-called eta-expansion allowing a method to be passed as a function argument.

In this case, it makes a difference. When defining as method, it is legal:

object Foo {    def bar(i: Int): Int = return i + i } 

In summary, you should only use return in methods that allow conditional (early) returns. See this post for a discussion on methods versus functions.

like image 34
0__ Avatar answered Oct 21 '22 21:10

0__