美文网首页
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