Both of the following function definations compile even though one uses = and other doesn't. Why? Is there an advantage of this behaviour?
def 1
def doWork(index:Int) = {
sleep((math.random*1000).toLong);
index;
}
def 2
def doWork(index:Int) {
sleep((math.random*1000).toLong);
index;
}
def 1 is what you want to use.
def 2 is called procedure syntax (discouraged) and actually means this:
def doWork(index:Int): Unit = {
sleep((math.random*1000).toLong)
index
}
So it's probably now what you want (since it doesn't return anything).
Not including an = sign declares a procedure. Procedures return Unit, i.e., don't return a value at all. As explained in the Scala language specification (from the link above):
A procedure definition is a function definition where the result type and the equals sign are omitted; its defining expression must be a block. E.g., def f(ps) {stats} is equivalent to def f(ps): Unit = {stats}.
In your second case, the return value simply gets suppressed to turn a function that returns Int into a procedure that returns Unit. While doing so, the compiler should issue a warning similar to
warning: a pure expression does nothing in a statement position
This should let you know that something fishy is going on, i.e., there is a statement that would normally result in the block returning a value (index; in your case), but it goes unused.
When you don't use "=" with def, it means your defined function will return unit.
And in the second function, you don't use "=", that means the defined function will return unit, but your function is returning index.
That's why it throws warning as it expects unit and discard the value.
Thanks
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.
I started learning Scala only a day ago, now I'm testing a few random codes to see how it behaves. I find it a quite interesting programming language, especially for its SCALAbility.
Any way, while trying some code, I "accidentally" ran this:
var myVal = println("test")
println(myVal)
and I was surprised that it runs successfully without any errors, and the output was simply:
test
()
so I tried to find out what data type was given to this variable
println(myVal.getClass)
and it was
void
What I understood is that, as we all know, the println() method returns void which is logically nothing and cannot be assigned, but I guess it's possible in Scala to do so (even though there is no type for variables called void).
So, if I suppose this is possible, I must have nothing into my variable, it must be empty, because it is void, why do I have () as output? and what will be the type myVal?
println("test") is an expression in Scala just like any other expression which means it evaluates to a value of particular type. println("test") returns a value () of type Unit. The value () might look a bit unusual initially, but it is nevertheless just a regular value. Consider the following
val x: Int = 42
val u: Unit = ()
The type Unit does not carry much semantic value. It tells us a side-effect was executed, but does not pin down exactly what kind of side-effect it was. Imagine compiler desugars definition of
def println(x: Any): Unit = Console.println(x)
to something like
def println(x: Any): Unit = {
Console.println(x) // execute side-effect
return () // return value
}
Note the return ().
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.
I am new to scala, and got a little doubt about function definition & default return type.
Here is a function definition:
def wol(s: String) = s.length.toString.length
The prompt says it's:
wol: (s: String)Int
But, the code didn't specify return type explicitly, shouldn't it default to Unit, which means void in Java.
So, what is the rules for default return type of a Scala function?
The return type in a function is actually the return type of the last expression that occurs in the function. In this case it's an Int, because #length returns an Int.
This is the work done by the compiler when it tries to infer the type. If you don't specify a type, it automatically gets inferred, but it's not necessarily Unit. You could force it to be that be stating it:
def wol(s: String): Unit = s.length.toString.length
EDIT [syntactic sugar sample]
I just remembered something that might be connected to your previous beliefs. When you define a method without specifying its return type and without putting the = sign, the compiler will force the return type to be Unit.
def wol(s: String) {
s.length.toString.length
}
val x = wol("") // x has type Unit!
IntelliJ actually warns you and gives the hint Useless expression. Behind the scene, the #wol function here is converted into something like:
// This is actually the same as the first function
def wol(s: String): Unit = { s.length.toString.length }
Anyway, as a best practice try to avoid using this syntax and always opt for putting that = sign. Furthermore if you define public methods try to always specify the return type.
Hope that helps :)
I am learning Scala and running below code .I knew functions, that do not return anything is procedures in Scala but when running below code why extra () is coming in output. Here in procedure i am just printing the value of 'value'.
Can someone explain about this.
class Sample{
private var value = 1
def test() {value += 2; println(value)}
def test2() = value
}
object Main2 extends App {
val my_counter = new Sample()
println(my_counter.test())
println(my_counter.test2())
}
3
()
3
The so-called "procedure syntax" is just "syntactic sugar" for a method that returns Unit (what you would call void in Java).
def sayHello(toWhom: String) {
println(s"hello $toWhom")
}
Is semantically equivalent (and gets actually translated) to:
def sayHello(toWhom: String): Unit = {
println(s"hello $toWhom")
}
Notice the explicit type and the equal sign right after the method signature.
The type Unit has a single value which is written () (and read unit, just like it's type). That's what you see: the method test prints value and then produces () of type Unit, which you then move on to print on the screen itself.
As noted in a comment, the "procedure syntax" is deprecated and will be removed in Scala 3.
Procedure syntax compiles to a method that returns unit.
calling toString on Unit produces "()"
You are printing out the result of test (which is Unit) so you see its string representation, () in the output.