2013-03-08 29 views
10

在Scala中,爲什麼咖喱函數可以很容易地直接傳遞給其他函數,但是當將它分配給val時,還需要將其部分應用於_?例如,給出的兩個功能:爲什麼Scala在分配給val時需要部分應用curried函數?

def curried(a: Int)(b: Int) = a + b 
def test(a: Int, f: Int => Int) = f(a) 

我可以很容易地通過curriedtest有:

test(5, curried(5)) 

,一切都是幸福的。但是,如果我只需撥打curried(5)我得到一個錯誤:如果我改變呼叫但是包括類型信息

scala> curried(5) 
<console>:9: error: missing arguments for method curried; 
follow this method with `_' if you want to treat it as a partially applied function 
       curried(5) 

,它的工作原理:

val 'curried: Int => Int = curried(5) 

任何人都可以解釋的合理不一致的背後,想必給定原始方法的類型定義,Scala編譯器可以推斷函數爲Int => Int

+0

在'val'的情況下,如果你給一個類型註解,你將不需要公開的部分應用程序'_'。 – 2013-03-08 23:19:58

回答

8

問題不是推斷類型,問題是推斷你的意圖。你犯了一個錯誤,還是你有意咖哩功能?

唉,尾部下劃線語法是形式語法,省略它是語法糖。

+0

這是有道理的,但是我確實將方法描述爲咖喱函數的事實已經描述了我的意圖。如果問題在於推斷意圖,爲什麼內聯可以? – 2013-03-09 00:46:19

+0

@MarkDerricutt我不確定你的意思是「內聯」,但是在所有情況下,你已經展示了它在哪裏工作,你聲明瞭你期望的結果,所以Scala繼續使用currying,因爲它符合你的期望。至於前者,斯卡拉不會隱式地咖喱,它會用尾部下劃線或類型匹配來明確地進行調整 - 如果你來自一種帶有隱含的壓縮的語言,那看起來可能不自然。然而,函數_declaration_聲明瞭多個參數列表,除了currying以外,這些列表對其他事物都很有用。 – 2013-03-09 01:17:10

+0

通過「內聯」,我的意思是在參數位置中使用(思考它,參數的賦值具有完全限定的類型信息,因此基本上與我的最後一個示例相同)。 我假定Scala顯式currying來自多個參數列表,不同於Haskell的方法,其中每個方法聲明都隱式地被curry調用,任何具有缺少參數的調用只會返回該位置的curried函數。 我的疑惑來自於「多參數列表== currying」的假設,顯然這不是特例。 – 2013-03-09 01:39:42

0

下劃線並不總是需要的。 From http://docs.scala-lang.org/cheatsheets/

val zscore = (mean:R, sd:R) => (x:R) => (x-mean)/sd 

currying,語法明顯。

def zscore(mean:R, sd:R) = (x:R) => (x-mean)/sd 

鑽營,明顯的語法

def zscore(mean:R, sd:R)(x:R) = (x-mean)/sd 

鑽營,糖語法。但隨後:

val normer = zscore(7, 0.4) _ 

需要尾隨下劃線得到部分,只對糖的版本。

相關問題