使用lazy val进行名称调用和call-by-value

时间:2013-06-13 04:37:34

标签: scala parameters lazy-evaluation callbyname

我想知道值传递的变量之间的差异,但是懒惰,并且在Scala中按名称传递变量。

我写这个例子试图展示,但我没有,我该怎么办?

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"

2 个答案:

答案 0 :(得分:2)

用“5”表示,就像,2,对吗?而“1”表示0?

这是Google面试中的一个问题吗?

这表示闭包由函数评估两次:

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

然后

scala> println(i)
4

那是在它之后。

HTH。

答案 1 :(得分:2)

看看这是否有帮助。

  • val在定义时执行
  • lazy val执行一次 但在第一时间参考
  • 执行
  • :=>名称传递 每次在参考时但不在定义时(想想 它像一个函数,一个函数在执行时执行 调用/引用,而不是在我们定义函数时),

    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("再次测试l")     callByValue({println(" l"); 0}); // l按值传递。因此,该块将被执行一次

输出

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