Question

I would like to know the difference between a variable passed by value, but lazy, and pass a variable by name in Scala.

I wrote this example to try to show but I do not, how should I do?

def callByValue(x : Unit) = {
x
x
}

def callByName(x : => Unit) = {
    x
    x
}

lazy val j = {println("initializing lazy"); 0}
var i = {println("initializing"); 0}

callByName(i = i + 1)
print(i + "\n")  // "5"

callByValue(j)
print(j + "\n")  // "1"
Was it helpful?

Solution

By "5" you mean, like, 2, right? And "1" means 0?

Is this one of those Google interview questions?

This shows the closure evaluated twice by the function:

scala> callByName {
     | println("calling")
     | i += 1
     | }
calling
calling

and then

scala> println(i)
4

That's after it was 2.

HTH.

OTHER TIPS

See if this helps.

  • val is executed at time of definition
  • lazy val is executed once but at first time of reference
  • :=> pass by name is executed everytime at time of reference but not at time of definition (think of it like a function, a function is executed at time of call/reference, not at time when we define a function),

    def callByValue(x : Unit) = {
        x  
        x 
    }
    
    def callByName(x : => Unit) = {
        x 
        x 
    }
    
    
        val i = {println("i"); 0}//print should  happen now at time of declaration. i is 0.
        lazy val j = {println("j"); 0} //no print because {...} will get executed when j is referenced, not at time of definition.
        val k = {println("k"); 0} //same as case of i, print should happen now. K should be 0
    
        //no special case. A val being passed like a regular function
        println("k test. K is val")
        callByValue (k) //no prints as K block is already evaluated.
    
    //passing a val to a function by name. The behavior will be same as K because i is already evaluated at time of definition. basically we are passing 0
        println("i test. i is val but passed by Name.");
        callByName(i);//I is passed by name. Thus the block will be executed everytime it is referenced 
    
        println("j test. It is passed lazy. It will be executed only once when referenced for 1st time")
        callByValue(j) //prints j once, assigns value 0 to j inside callByValue function. Note that because j is lazy, it the block {print j;0} is evaluated once when j was referenced for first time. It is not executed everytime j was referenced.
    
        println("test l")
        callByName({println("l");0});//l is passed by name. Thus the block will be executed everytime it is referenced
    

    println("test l again") callByValue({println("l");0});//l is passed by value. Thus the block will be executed once

Output

i <- when i was defined. val i = {println("i"); 0}
k <- when k was defined. {println("k"); 0}
k test. K is val <- no further prints of 'k' as the {println("k"); 0} has already been evaluated
i test. i is val but passed by Name. <- no furhter prints of 'i' as {println("i"); 0} is already evaluated
j test. It is passed lazy. It will be executed only once when referenced for 1st time
j <- note j is printed now instead of time of definition

test l
l <- we passed {print(l);0}. It will get executed everytime l is referenced. Thus two prints corresponding to {x;x} code of call by name
l
test l again
l <- only one print when {print(l);0} was passed by value
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top