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
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.
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.
Related
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
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.
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.
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
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.
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.
Im a Scala newbie and I get that its a really rich language. One thing that is getting me caught out syntax-wise is on function creation. I understand that braces {} are interpreted by the compiler as being synonymous with parentheses () in many contexts, but the following I still do not quite understand.
The following is the output from Scala REPL:
scala> def index = List {}
index: List[Unit]
scala> def index = List ()
index: List[Nothing]
Q1.
If I understand the above correctly, I am creating a function called index that creates a new List (new is omitted because of implicit call to apply method right?).
I see that Unit (equivalent to null in Java?) is the Type of my List when braces {} are used. But Nothing is the type when using parens ().
Q2.
Can someone explain, in simple terms (if possible), the difference between the use of {} and () in creating functions and also what Nothing represents?
Edit - So the following are equivalent?
def index = List {val a = 1; a}
def index = List ({val a = 1; a})
Im also struggling a bit with where the terms function and method seem to be used interchangeably.
Is it correct to say that both the above can both be considered either a function or method?
Or does it depend on who you talk to?
If I understand the above correctly, I am creating a function called index that creates a new List (new is omitted because of implicit call to apply method right?).
(new is omitted because of implicit call to apply method right?)
Yes, kind of. List.apply constructs the List and returns it to your method.
def index = List {} creates a method called index that creates a new List by calling List.apply.
Can someone explain, in simple terms (if possible), the difference between the use of {} and () in creating functions and also what Nothing represents?
The empty curly braces {} represent an anonymous function, rather than a simple list of elements. For example I can do:
scala> def index = List {val a = 1; a}
index: List[Int]
Your method is equivalent to (where the parentheses are omitted):
def index = List({})
The result of the anonymous function is passed to apply. When the braces are empty, the return type of the anonymous function is Unit. So we get List[Unit].
def index = List () always returns an empty List. However, because you have no annotations, the compiler cannot infer a type from this, so it is inferred as Nothing, which is a sub-type of every other type. This allows us to combine a List[Nothing] with a List[Int] and still compile.
I see that Unit (equivalent to null in Java?) ...
Unit is the return type of a method that doesn't return anything. Similar to void in Java, not null.
I am a beginning practitioner in Scala and I saw a few different syntax for calling a method. Some are nice, as ignoring parenthesis for a parameterless method, or ignoring the dot as in
1 to 10
but some really puzzle me. for instance:
breakable { ... }
this is simply a method call right? Can I also do that for more than one parameter or a parameter which is not a parameterless function?
Thanks
There are two standard ways of calling methods:
obj.method(params) // dot notation
obj method (params) // operator notation
The above can be modified in the following ways:
If params is a single parameter, you can replace () with {}.
If params is a single parameter and you are using operator notation, you can drop the parenthesis.
If method doesn't take parameters, you can drop (params) (that is, drop the empty ()).
If method ends with :, then it actually binds to the right in operator notation. That is, (params) method_: obj is equivalent to obj.method_:(params).
Either way, spaces are optional as long as identifiers can be told apart. So one can add spaces to the dot notation, like obj . method ( params ) or write .method(params) on the next line -- as often happens with call chaining --, as well as remove spaces from the operator notation, as in a+b.
There's also some stuff with tuple inference, but I try to avoid it, so I'm not sure of the exact rules.
None of these will explain the example you are confused about, however. Before I explain it, however, I'd like to show some syntactic sugars that can also be used to call methods:
obj(params) // equivalent to obj.apply(params)
obj.x = y // equivalent to obj.x_=(y), if obj.x also exists
obj(x) = y // equivalent to obj.update(x, y)
obj op= y // equivalent to obj = obj op y, if op is symbolic
~obj // equivalent to obj.unary_~; also for !, + and -, but no other symbol
Ok, now to the example you gave. One can import members of stable values. Java can do it for static methods with its static import, but Scala has a more general mechanism: importing from packages, objects or common instances is no different: it brings both type members and value members. Methods fall in the latter category.
So, imagine you have val a = 2, and you do import a._. That will bring into scope all of Int methods, so you can call them directly. You can't do +(2), because that would be interpreted as a call to unary_+, but you could call *(4), for example:
scala> val a = 2
a: Int = 2
scala> import a._
import a._
scala> *(4)
res16: Int = 8
Now, here's the rule. You can call
method(params)
If:
method was imported into scope.
You keep the parenthesis (even if there's only one parameter)
Note that there's a precedence issue as well. If you write obj method(params), Scala will presume method belongs to obj, even if it was imported into scope.
If we desugar this we will have:
breakable({ ... })
this matches signature
breakable: (op: ⇒ Unit): Unit
and uses so named call-by-name arguments (you may think of this as pass a block of code as argument)
More over scala allows you to write this:
scala> def foo (op1: => Unit)(op2: => Unit) = {op1;op2;}
foo: (op1: => Unit)(op2: => Unit)Unit
scala> foo { println(1) } { println(2) }
1
2
Above is the example of curried function
I have a loan pattern that applies a function n times where 'i' is the incrementing variable. "Occasionally", I want the function passed in to have access to 'i'....but I don't want to require all functions passed in to require defining a param to accept 'i'. Example below...
def withLoaner = (n:Int) => (op:(Int) => String) => {
val result = for(i <- 1 to n) yield op(i)
result.mkString("\n")
}
def bob = (x:Int) => "bob" // don't need access to i. is there a way use () => "bob" instead?
def nums = (x:Int) => x.toString // needs access to i, define i as an input param
println(withLoaner(3)(bob))
println(withLoaner(3)(nums))
def withLoaner(n: Int) = new {
def apply(op: Int => String) : String = (1 to n).map(op).mkString("\n")
def apply(op: () => String) : String = apply{i: Int => op()}
}
(not sure how it is related to the loan pattern)
Edit Little explanation as requested in comment.
Not sure what you know and don't know of scala and what you don't undestand in that code. so sorry if what I just belabor the obvious.
First, a scala program consist of traits/classes (also singleton object) and methods. Everything that is done is done by methods (leaving constructor aside). Functions (as opposed to methods) are instances of (subtypes of) the various FunctionN traits (N the number of arguments). Each of them has as apply method that is the actual implemention.
If you write
val inc = {i: Int => i + 1}
it is desugared to
val inc = new Function1[Int, Int] {def apply(i: Int) = i + 1}
(defines an anonymous class extending Function1, with given apply method and creating an instance)
So writing a function has rather more weight than a simple method. Also you cannot have overloading (several methods with the same name, differing by the signature, just what I did above), nor use named arguments, or default value for arguments.
On the other hand, functions are first classes values (they can be passed as arguments, returned as result) while methods are not. They are automatically converted to functions when needed, however there may be some edges cases when doing that. If a method is intended solely to be used as a function value, rather than called as a method, it might be better to write a function.
A function f, with its apply method, is called with f(x) rather than f.apply(x) (which works too), because scala desugars function call notation on a value (value followed by parentheses and 0 or more args) to a call to method apply. f(x) is syntactic sugar for f.apply(x). This works whatever the type of f, it does not need to be one of the FunctionN.
What is done in withLoaner is returning an object (of an anonymous type, but one could have defined a class separately and returned an instance of it). The object has two apply methods, one accepting an Int => String, the other one an () => String. When you do withLoaner(n)(f) it means withLoaner(n).apply(f). The appropriate apply method is selected, if f has the proper type for one of them, otherwise, compile error.
Just in case you wonder withLoaner(n) does not mean withLoaner.apply(n) (or it would never stop, that could just as well mean withLoaner.apply.apply(n)), as withLoaner is a method, not a value.