2017-06-24 83 views
2

更好地瞭解scala,我遇到了一個我無法解釋的行爲。 下面的代碼工作正常:爲什麼在scala中傳遞一些函數需要_

def triple(x: Double) = 3 * x 
Array(3.14,1.42,3.9).map(triple) 

但是,如果我叫斯卡拉小區功能的數學庫,然後我需要傳遞一個_爲它工作

def valueAtOneQuarter(f: (Double)=> Double) = f(0.25) 
valueAtOneQuarter(sqrt _) 

什麼特別之處_在這個上下文中來自前面一段代碼中的函數調用。

+2

它實際上對我來說工作正常,沒有下劃線在這兩種情況下 – Dima

+0

擴大對我的作品也是自動發生的,沒有必要像Dima說的那樣使用'_'。 –

回答

3

下劃線實際上擴展爲一個函數。

所以sqrt _變成函數a => sqrt(a)

您會注意到這個擴展函數與valueatonequarter方法的參數類型f匹配。

更一般地說,下劃線有時需要標記給編譯器以將方法(使用def聲明的方法)轉換爲函數(方法和函數相似但不是相同的東西)。編譯器會嘗試自動將該方法轉換爲函數,但在某些情況下,它需要額外的指針(如顯式類型聲明或_)。請參閱此處以獲取eta擴展和部分函數的完整說明:https://medium.com/@sinisalouc/on-method-invocations-or-what-exactly-is-eta-expansion-1019b37e010c

+0

這並不回答爲什麼它需要在一個情況下強調,而不是在另一個情況下。 – Dima

+0

謝謝迪馬 - 更新了答案。 – jsdeveloper

1

Scala中的方法和函數不相同。

您定義的方法是這樣的:

​​

但是你定義使用這樣的功能:當你將一個函數作爲參數傳遞給它必須是一個函數的方法

val func = (x: Double):Double => {...} 

,但不是一種方法。

所以你必須使用下劃線來從一個方法中創建一個函數。

有時Scala使用「Eta Expansion」功能將該方法自動轉換爲函數。但在某些情況下,您必須手動執行

+0

感謝似乎_在scala中的不同上下文中具有不同的含義。它幾乎就像是否存在一些差距_就是答案 – jtkSource

1

作爲回答,因爲現有答案不能真正解釋何時需要_,只是「有時」或「在某些情況下」。

在Scala中理解的一個非常重要的概念是預期類型。在你的第一個例子中,參數map的預期類型是Double => B,有一些未知的B;在第二個它是Double => Double。當期望的類型是函數類型並且方法名稱被傳遞時,它將被自動轉換爲函數。所以,正如評論所說,第二個例子沒有_。這是隻需要在沒有預期的類型,說

val f = sqrt _ 

也可能有問題時,該方法被重載,但只是添加_一般不會工作,要麼;相反,您將指定參數類型以顯示使用哪種方法,例如max(_: Int, _: Int)max(_: Double, _: Double)

感謝似乎_在斯卡拉在不同的上下文不同的含義

是,相當多的:What are all the uses of an underscore in Scala?

相關問題