美文网首页
Scala的call-by-name和call-by-value

Scala的call-by-name和call-by-value

作者: 小北觅 | 来源:发表于2020-01-09 15:17 被阅读0次

    结论:

    ①使用 :=>把函数参数声明成为call-by-name的

    ②Scala的解释器在解析函数参数(function arguments)时有两种方式:

    1. 传值调用(call-by-value):先计算参数表达式的值,再应用到函数内部;
    2. 传名调用(call-by-name):将未计算的参数表达式直接应用到函数内部

    ③每次使用传名调用时,解释器都会计算一次表达式的值。而使用传值调用时,表达式的值会提前计算好,只计算一次表达式的值。

    1. 例子

    object testCallByName {
      def main(args: Array[String]): Unit = {
        callByName(something())
      }
    
      def something() = {
        println("calling something")
        1 // return value
      }
      def callByValue(x: Int) = {
        println("x1=" + x)
        println("x2=" + x)
      }
      def callByName(x: => Int) = {
        println("x1=" + x)
        println("x2=" + x)
      }
    }
    

    运行结果如下:

    当调用callByName方法时:


    当调用callByValue方法时:

    2. 两者对比

    call-by-value在进入函数体之前就对参数表达式进行了计算,这避免了函数内部多次使用参数时重复计算其值,在一定程度上提高了效率。

    但是call-by-name的一个优势在于,如果参数在函数体内部没有被使用到,那么它就不用计算参数表达式的值了。在这种情况下,call-by-name的效率会高一点。

    object notUse {
    
      def main(args: Array[String]) = {
    
        val flag = true
        println(useOrNotUse(flag, 1, getANumber()))
      }
    
      def getANumber() = {
        println("getANumber调用了")
        2 // return value
      }
    
      def useOrNotUse(flag: Boolean, x: Int, y: => Int) = {
        if (flag) {
          x
        }
        else {
          x + y
        }
      }
    }
    

    方法useOrNotUse的第三个参数y被定义为call-by-name的。当flag=true时,方法useOrNotUse不需要使用到y。所以不会调用getANumber()方法。结果如下:

    当我们把flag设置为false时,需要用到y,此时才会调用getANumber()方法。此时运行结果如下:

    相关文章

      网友评论

          本文标题:Scala的call-by-name和call-by-value

          本文链接:https://www.haomeiwen.com/subject/qgxyactx.html