2012-03-03 3 views
7

Iは、次の2つの機能を定義することができます。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 _ 

を行う場合、これは

になり機能

パラメータを取らず、3つのIntパラメータを取り、Intを返す関数を返す関数のようです。なぜこれが起こるのですか?誰かが何が起こっているか説明できますか?

おかげ

+0

が重複する可能性が。何が区別されますか?](http://stackoverflow.com/questions/2720486/declaring-functions-two-ways-what-is-the-distinction) –

+0

重複は3番目の関連リンクでした。本当に、以前に尋ねられた質問を探してみてください - これは何度も何度も尋ねられました。私はリンクが最も重複していると思うが、私は個人的には[この回答](http://stackoverflow.com/questions/2529184/difference-between-method-and-function-in-scala/2530007#2530007)私の被験者の底に到達する。 –

+0

ところで、 'val add2'の代わりに' def add2'を書いたほうがはっきりしているでしょう。 –

答えて

9

これは、Scalaは実際に(ユーザーがアクセス可能)フィールドを持つが、その代わりにすべてのためにアクセサ(ゲッター)を持っていないの奇妙な副作用です。お守り:

scala> val i = 1 
i: Int = 1 

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

理由はiが実際に基礎となる(隠された、アクセスできない)フィールドへのアクセサ(def i: Int)であるということです。単なるメソッドなので、_はそれを関数に変換します。アクセサは引数をとらないため、パラメータを必要としない関数があります。

+0

+1しかし、私はこの効果が_strange_だとは思わない – Odomontois

1

効果は明確にRex Kerr's answerに記載されていますが、add2はすでに部分的に適用された関数を表す値であることに注意してください。デリゲート。 add1 _の式とadd2の値の型を比較す​​ることができます。

2

Scalaには、機能とメソッドの両方がありますが、それらは全く同じではありません。

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

これはメソッド(関数ではありません!!)です。

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

どのような機能値(方法ではありません!!)が割り当てられます。メソッド名の後にアンダースコアを書く

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> 
関連する問題