22

Does anyone know the type of => Unit in scala? I don't know the meaning of => Unit and how to use it. I defined a function like below:

def test(code: => Unit){ print("start ...") code print("end ....") } test(print(1)) 

Does it means a function with any arguments returning Unit?

Thanks

4 Answers 4

25

This kind of parameter are called by-name parameter

=> B represents a block a of code which return a B value, their purpose is that they are evaluated only when you call the parameter.

def foo(code: => Int) { println("Not yet evaluated") val result = code println("parameter evaluated %s, is it an int ? %s " format ( result, result.isInstanceOf[Int]) ) } 

And you can call foo in the following way :

foo(1) 

or

val a = 3 val b = 5 foo { val c = a * a c * b } 

The other style of passing parameter is by-value : parameters are evaluated before they are sent to the method

def foo(code : Int) { println("Parameter already evaluated") val result = code println("parameter evaluated : " + result) } 

References

Extract from the Book Functionnal Programming in Scala

More differences between by-name parameter and by-value parameter illustrated

Sign up to request clarification or add additional context in comments.

3 Comments

Regarding your calling example, it's more idiomatic to drop the parentheses around the argument when passing in a multiline code block: foo { ... }.
Not a good answer, because it doesn't make the distinction of a by name parameter versus a lazy (call by need) parameter.
@Dianel Could you help me about how I can enhance my answer, for example a kind of situation which make a clear distinction those two cases ? @Aaron edited
13

In x: => Type the x is a call by name parameter. That's different than taking an argument which is a function taking no arguments: x: () => Type

2 Comments

Specifically it's different because at the call-site the expression to be evaluated is given directly, not as a function (thus test(print(1)) instead of test(() => print(1))).
Thanks for the part about "function taking no arguments": I was looking for an explanation about that syntax. Of course, it makes total sense, so should have figured it out myself :)
10

This is called a by name parameter, as related to call-by-name parameter evaluation strategy. Please see the linked wikipedia article for similar, but not identical, ways of passing parameters.

To explain it better, let's consider first the two most common parameter evaluation strategies: call by value and call by reference.

Call by value is by far the most common evaluation strategy. It is the sole strategy in Java, for instance, and the default strategy in C. Consider, for instance, this simple Java program:

public class ByValue { static public void inc(int y) { y++; } static public void main(String... args) { int x = 0; inc(x); System.out.println(x); } } 

It will print 0, because x's value is copied to y, so that when y is incremented it doesn't change the original value in x. Contrast this with this C++ program with call-by-reference:

#include <stdio.h> void inc(int &y) { y++; } int main() { int x = 0; inc(x); printf("%d\n", x); } 

This will print 1, because the reference to x is passed to inc, instead of x's value.

Note that Java passes objects references by value, which leads some to claim it does call by reference. This is not true, to the extent that if you were to assign a new object to a parameter of a function, it would not be reflected in the function's caller.

So, what does a call by name looks like? In a call by name, neither value nor reference is passed. Instead, the whole code is passed, and everywhere the parameter is used, the code is executed and its result used. For example:

object ByName { def incIfZero(y: => Int): Int = if (y == 0) y + 1 else y def main(args: Array[String]) { var x = 0 x = incIfZero( { val tmp = x; x += 1; tmp } ) println(x) } } 

This example prints 2 instead of 1, because the block of code passed as parameter is evaluted twice. When executing, it's as if the second line in the main was written like this:

x = if ({ val tmp = x; x += 1; tmp }) { val tmp = x; x += 1; tmp } + 1 else { val tmp = x; x += 1; tmp } 

Now, by name parameters have at least three interesting uses:

  1. It can be used to delay the execution of something until the proper time.
  2. It can be used to avoid the execution in some situations.
  3. It can be used to execute some block of code multiple times.

The first and last cases are pretty obvious, I think. Here's an example of the second case:

implicit def fromBoolean(b: Boolean) = new { def and(that: => Boolean): Boolean = if (b) that else b } val x = 0 (x > 0) and (10 / x > 0) 

If that was not a by name parameter, there would be an exception thrown at the last line. As it is, it will just return false.

2 Comments

@ashy_32bit Maybe. I think people tend to misunderstand by-name parameters, confusing them with functions, and then stumbling over the fact that they are not in painful ways.
@DanielC Sobral: Awesome in depth answer. It's even better than the one in the "Functional Programming Principles in Scala" Coursera course. It might be worth putting up a page which contains an online REPL and let people "experiment" with the code to more specifically "experience" the difference. An explanation in test is just sufficiently abstract enough, the concept is difficult to grasp, especially if one has extensively mostly used Java for many years.
1

It means call-by-name, which basically means that the value is calculated when used in your function. As opposed to call-by-value which is default in Java (and Scala with regular type syntax), where the value is calculated before the method is called. A Unit type would not make much sense in call-by-value I guess..

This is typically used to create functions that behave as custom control structures, or things like timing or logging as in your example. Stuff you often use AOP to do in Java.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.