2012-03-03 39 views
7

我可以定義以下兩個功能:爲什麼部分函數應用於2個函數,它們以2種不同的方式定義相同的事物會返回不同的結果?

def add(a: Int, b: Int, c: Int) = a + b + c 

這導致

add: (a: Int, b: Int, c: Int)Int 

val add2 = (a: Int, b: Int, c: Int) => a + b + c 

這導致

add2: (Int, Int, Int) => Int = <function3> 

兩個這些都是做同樣的事情,但以不同的方式定義的函數,我不明白的是,如果我繼續和定義一個部分應用功能如下:

def a = add _ 

這導致

a: (Int, Int, Int) => Int = <function3> 

預期,函數接受3個參數,並返回一個int,但如果我不

def a2 = add2 _ 

這導致

a2:() => (Int, Int, Int) => Int = <function0> 

這似乎是一個函數,它不接受任何參數,並返回一個接受3個Int參數並返回一個Int的函數。爲什麼會發生?有人可以解釋發生了什麼嗎?

感謝

+0

可能重複。有什麼區別?](http://stackoverflow.com/questions/2720486/declaring-functions-two-ways-what-is-the-distinction) – 2012-03-03 14:04:13

+0

重複是第三個相關的鏈接。真的,試着去尋找以前提出的問題 - 這個問題已經被問了很多次。雖然我認爲該鏈接是最接近的副本,但我個人建議[這個答案](http://stackoverflow.com/questions/2529184/difference-between-method-and-function-in-scala/2530007#2530007)我的深入到主題的底部。 – 2012-03-03 14:05:56

+0

哦,順便說一下,如果你寫'def add2'而不是'val add2',或許你會更清楚。 – 2012-03-03 14:07:07

回答

9

這是斯卡拉實際上不是有(用戶訪問)領域,而是具有的一切存取(吸氣)一個奇怪的副作用。注意:

scala> val i = 1 
i: Int = 1 

scala> i _ 
res0:() => Int = <function0> 

的原因是i實際上是一個存取(def i: Int)到底層(隱藏,無法訪問)場。由於這只是一種方法,因此_會將其轉換爲函數。訪問器不接受任何參數,這就是爲什麼你有一個不帶參數的函數。

+0

+1但我不認爲這種效果是_strange_ – Odomontois 2012-03-03 05:44:21

1

效果在Rex Kerr's answer中有明確的描述,但您應該注意add2的值已經代表部分應用的功能,例如,代表。 爲了演示您可以比較add1 _表達式和add2值的類型。

scala> def getManifest[T](x:T)(implicit m:scala.reflect.Manifest[T]) = m 
getManifest: [T](x: T)(implicit m: scala.reflect.Manifest[T])scala.reflect.Manifest[T] 

scala> getManifest(add1 _) == getManifest(add2) 
res14: Boolean = true 
2

Scala既有功能又有方法,它們不是完全相同的東西。

def add(a: Int, b: Int, c: Int) = a + b + c 

其中定義了一種方法(不是函數!!)。

val add2 = (a: Int, b: Int, c: Int) => a + b + c 

哪個分配了add2函數值(不是方法!!)。

的方法不能是最終值,而功能:

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

scala> add2 
res1: (Int, Int, Int) => Int = <function3> 

scala> val a = add 
<console>:8: error: missing arguments for method add; 
follow this method with `_' if you want to treat it as a partially applied function 
     val a = add 
      ^

scala> val a2 = add2 
a2: (Int, Int, Int) => Int = <function3> 

方法名稱後寫下劃線可以顯式轉換的方法成一個函數:

scala> add _ 
res2: (Int, Int, Int) => Int = <function3> 

但如果你在一個值後面寫下劃線,它會轉換爲一個不帶參數的函數,返回類型爲:

scala> val s = "" 
s: String = "" 

scala> val i = 1 
i: Int = 1 

scala> s _ 
res3:() => String = <function0> 

scala> i _ 
res4:() => Int = <function0> 

因此,如果值本身是一個函數,文字下劃線後,將獲得不採用任何參數與函數的返回類型的新功能:聲明功能兩個方面的

scala> add2 _ 
res5:() => (Int, Int, Int) => Int = <function0> 
相關問題