2014-09-25 30 views
0

給定一個重載函數,以函數作爲參數。此參數函數沒有參數:Scala:帶功能的重載函數作爲參數

def func(param:() => Unit): Unit = { 
    param() 
} 

def func(param: Int): Unit = { 
    println(param) 
} 

在呼籲func一個匿名函數可以完美運行:

func(() => println("it works")) 

使用純函數失敗:

def functionAsParam(): Unit = { 
    println("it works") 
} 

func(functionAsParam) 

顯然,斯卡拉評估functionAsParam並且不要將該函數本身傳遞給func。問題:我如何(作爲提供func的庫的用戶)通過非匿名函數?

回答

2

有幾種方法可以做到這一點。要麼你明確地傳遞給函數的參數:

scala> func(() => functionAsParam) 
it works 

scala> func (functionAsParam _) 
it works 

(這兩種情況略有不同,雖然,因爲在第一個例子,你構造新的匿名功能與其他功能的讀出,並在第二個例子中,你表明,這個功能應該還沒有被添加_)

評估,或者你創建一個變量,它是一個函數,並沿着它傳遞:

val fval =() => println("It works") 
scala> func(fval) 
It works 
+1

我認爲你的話不太正確,在parens。下劃線的意思是「把我變成一個功能」。兩種方式是一樣的。不確定任何人都會使用第一種方式,但如果他們這樣做了,他們會在調用風格時使用parens。 http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#method-values – 2014-09-25 21:30:56

+0

感謝您的評論,實際上那些以第一種方式做它的人是我,因爲第二方式感覺不那麼「直觀」。 – Ashalynd 2014-09-25 22:32:28

2

錯誤來自您定義方法的事實,但您的func需要一個函數。是的,在scala中超載有問題(在其他方面也是如此)。要解決它,你需要手動的方法轉換成一個功能(這就是所謂的ETA-expantion):

func(functionAsParam _) 

如果打開-Xprint:typer你會看到scalac擴展你的方法到一個函數:

val res4: Unit = func({ 
    (() => functionAsParam()) 
}); 
+0

第一個說法是錯誤的,因爲它的工作原理沒有過載。如果需要一個func,eta-expand會發生,但是如果不先選擇一個重載的符號,就不能這麼說。 – 2014-09-25 21:35:59