As I understand it, in Scala, a function may be called either
- by-value or
- by-name
For example, given the following declarations, do we know how the function will be called?
Declaration:
def f (x:Int, y:Int) = x;
Call
f (1,2)
f (23+55,5)
f (12+3, 44*11)
What are the rules please?
There are already lots of fantastic answers for this question in Internet. I will write a compilation of several explanations and examples I have gathered about the topic, just in case someone may find it helpful
INTRODUCTION
call-by-value (CBV)
Typically, parameters to functions are call-by-value parameters; that is, the parameters are evaluated left to right to determine their value before the function itself is evaluated
call-by-name (CBN)
But what if we need to write a function that accepts as a parameter an expression that we don't to evaluate until it's called within our function? For this circumstance, Scala offers call-by-name parameters. Meaning the parameter is passed into the function as it is, and its valuation takes place after substitution
A call-by-name mechanism passes a code block to the call and each time the call accesses the parameter, the code block is executed and the value is calculated. In the following example, delayed prints a message demonstrating that the method has been entered. Next, delayed prints a message with its value. Finally, delayed returns ‘t’:
PROS AND CONS FOR EACH CASE
CBN: +Terminates more often * check below above termination * + Has the advantage that a function argument is not evaluated if the corresponding parameter is unused in the evaluation of the function body -It is slower, it creates more classes (meaning the program takes longer to load) and it consumes more memory.
CBV: + It is often exponentially more efficient than CBN, because it avoids this repeated recomputation of arguments expressions that call by name entails. It evaluates every function argument only once + It plays much nicer with imperative effects and side effects, because you tend to know much better when expressions will be evaluated. -It may lead to a loop during its parameters evaluation * check below above termination *
What if termination is not guaranteed?
-If CBV evaluation of an expression e terminates, then CBN evaluation of e terminates too -The other direction is not true
Non-termination example
Consider the expression first(1,loop)
CBN: first(1,loop) → 1 CBV: first(1,loop) → reduce arguments of this expression. Since one is a loop, it reduce arguments infinivly. It doesn’t terminate
DIFFERENCES IN EACH CASE BEHAVIOUR
Let's define a method test that will be
Case1 test(2,3)
Since we start with already evaluated arguments it will be the same amount of steps for call-by-value and call-by-name
Case2 test(3+4,8)
In this case call-by-value performs less steps
Case3 test(7, 2*4)
We avoid the unnecessary computation of the second argument
Case4 test(3+4, 2*4)
Different approach
First, let's assume we have a function with a side-effect. This function prints something out and then returns an Int.
Now we are going to define two function that accept Int arguments that are exactly the same except that one takes the argument in a call-by-value style (x: Int) and the other in a call-by-name style (x: => Int).
Now what happens when we call them with our side-effecting function?
So you can see that in the call-by-value version, the side-effect of the passed-in function call (something()) only happened once. However, in the call-by-name version, the side-effect happened twice.
This is because call-by-value functions compute the passed-in expression's value before calling the function, thus the same value is accessed every time. However, call-by-name functions recompute the passed-in expression's value every time it is accessed.
EXAMPLES WHERE IT IS BETTER TO USE CALL-BY-NAME
From: https://stackoverflow.com/a/19036068/1773841
Simple performance example: logging.
Let's imagine an interface like this:
And then used like this:
If the info method doesn't do anything (because, say, the logging level was configured for higher than that), then computeTimeSpent never gets called, saving time. This happens a lot with loggers, where one often sees string manipulation which can be expensive relative to the tasks being logged.
Correctness example: logic operators.
You have probably seen code like this:
Imagine you would declare && method like this:
then, whenever ref is null, you'll get an error because isSomething will be called on a nullreference before being passed to &&. For this reason, the actual declaration is:
In a Call by Value, the value of the expression is pre-computed at the time of the function call and that particular value is passed as the parameter to the corresponding function. The same value will be used all throughout the function.
Whereas in a Call by Name, the expression itself is passed as a parameter to the function and it is only computed inside the function, whenever that particular parameter is called.
The difference between Call by Name and Call by Value in Scala could be better understood with the below example:
Code Snippet
Output
In the above code snippet, for the function call CallbyValue(System.nanoTime()), the system nano time is pre-calculated and that pre-calculated value has been passed a parameter to the function call.
But in the CallbyName(System.nanoTime()) function call, the expression "System.nanoTime())" itself is passed as a parameter to the function call and the value of that expression is calculated when that parameter is used inside the function.
Notice the function definition of the CallbyName function, where there is a => symbol separating the parameter x and its datatype. That particular symbol there indicates the function is of call by name type.
In other words, the call by value function arguments are evaluated once before entering the function, but the call by name function arguments are evaluated inside the function only when they are needed.
Hope this helps!
Call by value is general use case as explained by many answers here..
I will try to demonstrate call by name more simple way with use cases below
Example 1:
Simple example/use case of call by name is below function, which takes function as parameter and gives the time elapsed.
Example 2:
apache spark (with scala) uses logging using call by name way see
Logging
trait in which its lazily evaluates whetherlog.isInfoEnabled
or not from the below method.Here is a quick example I coded to help a colleague of mine who is currently taking the Scala course. What I thought was interesting is that Martin didn't use the && question answer presented earlier in the lecture as an example. In any event I hope this helps.
The output of the code will be the following:
CallByName
is invoked when used andcallByValue
is invoked whenever the statement is encountered.For example:-
I have a infinite loop i.e. if you execute this function we will never get
scala
prompt.a
callByName
function takes aboveloop
method as an argument and it is never used inside its body.On execution of
callByName
method we don't find any problem ( we getscala
prompt back ) as we are no where using the loop function insidecallByName
function.a
callByValue
function takes aboveloop
method as a parameter as a result inside function or expression is evaluated before executing outer function there byloop
function executed recursively and we never getscala
prompt back.As i assume, the
call-by-value
function as discuss above pass just the values to the function. According toMartin Odersky
It is a Evaluation strategy follow by a Scala that play the important role in function evaluation. But, Make it simple tocall-by-name
. its like a pass the function as a argument to the method also know asHigher-Order-Functions
. When the method access the value of passed parameter, it call the implementation of passed functions. as Below:According to @dhg example, create the method first as:
This function contain one
println
statement and return an integer value. Create the function, who have arguments as acall-by-name
:This function parameter, is define an anonymous function who have return one integer value. In this
x
contain an definition of function who have0
passed arguments but returnint
value and oursomething
function contain same signature. When we call the function, we pass the function as a argument tocallByName
. But in the case ofcall-by-value
its only pass the integer value to the function. We call the function as below:In this our
something
method called twice, because when we access the value ofx
incallByName
method, its call to the defintion ofsomething
method.