2013-08-02 33 views
1

一個呼叫按姓名是expensiveOperation()將不會在下面的例子得到運行好處:斯卡拉的call-by-名字 - 聲明參數未使用

呼叫按值:

def test(x: Int, y: Int): Int = x * x 

// expensiveOperation is evaluated and the result passed to test() 
test(4, expensiveOperation()) 

的call-by-名稱:

def test(x: Int, y: => Int): Int = x * x 

// expensionOperation is not evaluated 
test(4, expensiveOperation()) 

我的問題,雖然是你爲什麼要聲明一個函數參數(在我的情況下,y),當你不打算使用它呢?

+0

接不接'y'作爲參數?你想要什麼 – Jatin

+0

準確!我只是重複Martin Odersky在函數式編程課程中給出的例子 - https://www.coursera.org/course/progfun –

回答

4

你的例子是有點做作,考慮下面的代碼

def test(x: Boolean, y: => Int): Int = if(x) y else 0 

// expensionOperation is not evaluated 
test(false, expensiveOperation()) 

當第一個參數是假的你節省大量的時間不評估昂貴的操作。

+0

啊,我明白了。非常感謝!! –

2

這僅僅是一個人爲的例子來說明名稱調用的思想,即如果從不調用傳入的參數,則永遠不會對其進行評估。

也許一個更好的例子是以下幾點:

trait Option[+T] { 
    def getOrElse[B >: A](default: => B): B 
} 

如果OptionSome,然後包裹值返回和default不會求。如果它是None並且僅當它是None時,default將被評估(並因此返回)。

2

使用記錄是一個更好的例子:

def debug(msg: String) = if (logging.enabled) println(msg) 

debug(slowStatistics()) // slowStatistics will always be evaluated 

雖然呼叫按姓名的情況下:

def debug(msg: => String) = if (logging.enabled) println(msg) 

debug(slowStatistics()) // slowStatistics will be evaluated only if logging.enabled 
+0

在日誌中使用名義形式參數的問題是,他們經常會使它更加昂貴。例如,像logger.debug(「Made it」)這樣的常見用法需要實例化編譯器生成的thunk類,以保存實際上是編譯時常量(無論是否啓用「調試」級別)。 –

+0

@RandallSchulz可悲的是,沒錯。該名稱參數通過相對昂貴的關閉來捕獲。 –