scala-傳名函數和傳值函數


Scala的解釋器在解析函數參數(function arguments)時有兩種方式:先計算參數表達式的值(reduce the arguments),再應用到函數內部;或者是將未計算的參數表達式直接應用到函數內部。前者叫做傳值調用(call-by-value),后者叫做傳名調用(call-by-name)。

傳值函數和傳名函數

object Add {  
  def addByName(a: Int, b: => Int) = a + b   
  def addByValue(a: Int, b: Int) = a + b   
}

 

傳名函數和傳值函數在編譯器中區別: 

  addByName(2, 2 + 2)  
->2 + (2 + 2)  
->2 + 4  
->6  
  
  addByValue(2, 2 + 2)  
->addByValue(2, 4)  
->2 + 4  
->6  

可以看出,在進入函數內部前,傳值調用方式就已經將參數表達式的值計算完畢,而傳名調用是在函數內部進行參數表達式的值計算的。

這就造成了一種現象,每次使用傳名調用時,解釋器都會計算一次表達式的值。對於有副作用(side-effect)的參數來說,這無疑造成了兩種調用方式結果的不同。

因此, 在實際的使用中: 

傳值調用在進入函數體之前就對參數表達式進行了計算,這避免了函數內部多次使用參數時重復計算其值,在一定程度上提高了效率。

但是傳名調用的一個優勢在於,如果參數在函數體內部沒有被使用到,那么它就不用計算參數表達式的值了。在這種情況下,傳名調用的效率會高一點。

package com.doggie  
  
object WhyAlwaysMe {  
  var flag: Boolean = true  
  def useOrNotUse(x: Int, y: => Int) = {  
    flag match{  
      case true => x  
      case false => x + y  
    }  
  }  
  def main(args: Array[String]) =   
  {  
    println(useOrNotUse(1, 2))  
    flag = false  
    println(useOrNotUse(1, 2))  

 

 

=> Unit 與 () =>Unit的區別

簡單來說, => Unit是 傳名函數, 只傳入了一個表達式, 在調用時才會去執行, 使用 code調用

() => 是傳值函數, 傳入的計算后的值, 使用 code() 調用

package main.scala

/**
  * Created by wenbronk on 2017/9/12.
  */
object TestScala {

  def main(args: Array[String]): Unit = {
//    println( addInt(3, 5))
//    println(time())
    delayTime({
      println("2222");
      time()
    })
    delayTime2({
      println("333");
      time
    })
  }

  def delayTime2(t: () => Long): Unit = {
    println("執行...")
    println( t() )
    println("jiesu..")
  }

  def delayTime(t: => Long): Unit = {
    println("執行開始")
    println(t)
    println("執行結束")
  }

  def time() = {
    println("獲取時間內, 單位為 納秒")
    System.nanoTime()
  }

}

執行結果: 

 

 

 

 

http://blog.csdn.net/asongoficeandfire/article/details/21889375

http://www.aboutyun.com/thread-10864-1-3.html

http://scalagroup.group.iteye.com/group/topic/26303


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM