Suppose I have the following code example in Scala:
def myfunc = {
println("hello")
10
}
val myParam = myfunc
When this code runs, myfunc is executed, meaning that the console will print "hello" and myfunc will return the value of 10.
Let's say that I want myParam to hold the function myfunc without invoking it. How can I do it?
Scala differentiates between methods and functions
With def you define a method and with val a function.
Functions can be assigned to a variable without Parentheses myfunc and are called with Parentheses myfunc()
There is a short conversion syntax to assign a method as a function to a variable
mymethod(_) //use as many underscores as arguments.
However it does not work for zero arguments.
For zero arguments the only option is
def mymethod = {
println("hello")
10
}
val myfunc = () => mymethod
See How to use functions as variables (values) in Scala (but please note that the m _-syntax, mentioned in the blog post, will be deprecated in the future).
Given there is a side-effect in myFunc method
def myfunc = {
println("hello") <== side-effect here
10
}
tradition is to anyways hint at that with parenthesis ()
def myfunc() = {
println("hello")
10
}
which has the added bonus of being less confusing regarding eta expansion.
Related
Referring to following question in SO, what is the usefulness of passing Unit to a function instead of () or vice versa?
Functions without arguments, with unit as argument in scala
From what I can tell you would like to know what is the difference between these two method definitions, and why one would use Unit over () in the function parameter.
def func1(f:Unit=>String) = {
println(f)
}
def func2(f:()=>String) = {
println(f)
}
the difference can be highlighted by looking at the output of this code:
func1(Unit => "hello")
func2(() => "hello" )
you may be surprised to see this output:
<function1>
<function0>
Unit=>String is actually a function with 1 parameter. While ()=>String is a function with 0 parameters.
In Scala () could mean two things
it could be used for Unit e.g. val x:Unit = ()
it can be use to represent no parameters.
In func2, it is a function with no parameters.
"Unit" in func1 is actually the abstract class in the scala package (of which there is only one value "Unit" or "()"). So when the function Unit => String was defined, what we defined was a function that takes a parameter of type Unit as a parameter, and returns a value. Not a Function that takes no parameters.
A final tweak to the code to highlight the difference:
def func1(f:Unit=>String) = {
println(f(Unit))
}
def func2(f:()=>String) = {
println(f())
//println(f(Unit)) - does not compile
}
func1(Unit => "hello")
func2(() => "hello" )
Will output hello twice.
I'd suggest that func2 or () is generally what people want, and not func1 or "Unit"
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.
I created one function:
def ignore(f: Unit => Unit) = {
userDisabled = true
f
userDisabled = false
}
Now I get a warning:
a pure expression does nothing in statement position; you may be omitting necessary parentheses
When I add the parentheses, and write f(), I get:
Adaptation of argument list by inserting () has been deprecated: this is unlikely to be what you want. signature: Function1.apply(v1: T1): R given arguments: after adaptation: Function1((): Unit)
What am I doing wrong?
You probably wanted to declare ignore as
def ignore(f: () => Unit) = {
userDisabled = true
f()
userDisabled = false
}
With is function with 0 arity that returns Unit
Currently you have a 1 arg function that expects parameter of type Unit. There is only one value with such type and it is ().
When you simply say f, you do nothing, you don't call the function, hence the first warning. It is as if you just put:
userEnabled = true
42
userEnabled = false
When you say f() you are not passing an argument to a function that expects one. Scala can put there Unit for you, but it is deprecated, hence the second warning. You should call it as f(()).
Another option could be call by name parameter
def ignore(f: => Unit) = {
userDisabled = true
f
userDisabled = false
}
in that case f would cause side effects to happen each time you use it in the method body. This is the most common way of doing such thing as from caller perspective you can just say
ignore {
//code
}
instead of
ignore(() => {
//code
})
Writing a function without parenthesis, f, is an indication that it has no side effects, that the function is "pure". Since your function call without parens isn't the last statement, it would not be returned, and thus has no overall effect.
When you right this f() you're writing that your function takes no arguments. But it really does! It takes something of type Unit. Before Scala used to infer this for you but due to several issues you must now, since 2.11, provide it manually as f(())
I have following Currying function declaration:
def logString(count: Int)(fun:() => Unit) {
for (n <- 1 to count) { fun }
}
I call this function in this way:
logString(3) { () => print("I") }
The result is nothing - just no output.
Then I just add brackets after "fun" function invocation, inside the body of Currying function declaration:
def logString(count: Int)(fun:() => Unit) {
for (n <- 1 to count) { fun() }
}
The result becomes what is expected:
III
Is this some Scala bug, or there is some rule that I missed when learning Scala?
I know that there is rule that when you declare function like this:
def myFun = 1
we can not invoke it with brackets - the compilation fails.
But having different results when invoking a function with and without brackets seems more like a bug.
Am I right or I miss something about Scala?
Look at the type of fun, it's fun: () => Unit. You can think of that as meaning that when you call it with (), you get Unit in return. Without explicitly calling it, fun refers to the function as a value, not the result of calling it. This is the essence of the concept of higher-order functions.
If it had type fun: => Unit, simply mentioning fun would cause it to be executed, in which case there would be no way to refer the function as a value.
When you have such a declaration
val x = 10
this is a value definition. The value x can be an integer like in this case,
but it can also be a function.
val y = () => println("i'm a function")
However either way, if you call it without parenthesis nothing will happen.
scala> val x = 10
x: Int = 10
scala> val y = () => println("i'm a function")
y: () => Unit = <function0>
scala> x
res0: Int = 10
scala> y
res1: () => Unit = <function0>
When you have a function definition like this:
def z() = println("i'm a function def")
Then you can omit parenthisis and call it without it.
scala> def z() = println("i'm a function def")
z: ()Unit
scala> z
i'm a function def
In your case fun is like a value definition (it's a value parameter).
What happens is that, when Scala evaluates your for expression it will just do nothing with fun.
Just the same as if you did y vs y() from the example above.
I just wanted to share the information summarized by me based on the very helpful answers answers above and some additional research. Might be would be helpful for someone else also.
Functions can be declared in two ways in Scala:
- "call-by-name" - they are represented in the byte code as normal Java functions in a straightforward way.
- "call-by-value" - from Scala's abstract point of view they are stored in variables. Actually in the Byte code they are stored in classes implementing Single Abstract Method interfaces (SAM) and passed around as method parameters or as normal variables.
When we invoke a "call-by-name" function that does not take parameters it is always executed no matter how we call it with or without brackets.
So now myFunction and myFunction() is just the same.
When we invoke a "call-by-value" function that does not take parameters we have two cases:
- when we do not have brackets after it - myFunction - we just refer to the variable pointing to the function without executing function itself.
- when we have brackets - myFunction() - we actually call (execute) the function.
Different ways to declare function:
def myFunction = 5 * 5
This is call-by-name function. Declared this way no brackets allowed when calling it. So calling myFunction() will not compile. Call it this way: myFunction
def myFunction() = 5 * 5
This is call-by-name function. Can call the function with and without brackets - the effect is the same. So myFunction and myFunction() is just the same.
def myFunction = () => 5 * 5
This is call-by-value function (even when declared as def not val) . When calling it with brackets - myFunction() - function is executed, when calling it without brackets - myFunction - function is NOT executed - just val holding it is being mentioned.
Similarly if we declare function as other function's parameter:
def enclosingFunc(myFunction: => Void)
This is call-by-name function. Inside enclosing function it will be executed only if called without brackets - myFunction. With brackets - myFunction() - will not compile.
In this case enclosingFunc could be called this way:
enclosingFunc(n = 1; n +=1)
def enclosingFunc(myFunction: () => Int)
This is call-by-value function. It matters how we invoke it in the body of enclosing function. If invoke it without brackets - myFunction - it will NOT be executed, but we just refer to the object holing it. If invoke it with brackets - myFunction() - it will be called and executed.
In this case enclosingFunc could be called only in this way:
enclosingFunc( () => n = 1; n +=1)
In the first example the function fun doesn't isn't invoked, it juts sort of sits there. Adding the parenthesis cause the passed-in function to be evaluated.
A few times I saw a Scala code like that:
object Doer{
def doStuff(op: => Unit) {
op
}
}
Invoked in this way:
Doer.doStuff{
println("Done")
}
What is strange for me is how a function is passed to another function as just a block of code between curly braces. And there is even no parentheses that normally mark the beginning and end of argument list.
What is the name of this Scala syntax/feature? In what cases I can use it? Where is it documented?
This is called either a nullary function or a thunk, and is an example of call-by-name evaluation: http://www.scala-lang.org/old/node/138
You can use nullaries pretty much anywhere you have a parameter list. They are basically just syntactic sugar around zero-argument functions that make them look like ordinary values, and are invoked whenever they are referenced.
So
def doSomething(op: => Unit) {
op
}
doSomething {
println("Hello!")
}
is exactly the same as:
def doSomething(op: () => Unit) {
op()
}
doSomething(() => println("Hello!"))
The one thing to keep in mind with nullaries is they are invoked every time they are referenced, so something like:
def foo(op: => Int) = op + op
foo {
println("foo")
5
}
will print "foo" twice.
Edit: To expand on Randall's comment, one of the big ways that a nullary function differs from a zero-arg function is that nullaries are not first-class values. For example, you can have a List[() => Int] but you cannot have a List[=> Int]. And if you had something like:
def foo(i: => Int) = List(i)
you are not adding the nullary function to the list, only its return value.