scalaを学ぶ前は、主にjavaとpythonを使って日常の開発作業を行っていました。印象として、methodとfunctionの違いを特に意識して区別することはありませんでした。この関係は、私たちが日常生活で質量と重量を特に区別しないのと同じようなものです。しかし、それらの間には確かに違いがあり、その違いはまた、それらの間に繋がりがあるという基盤の上に成り立っています!
如何定义
まず、英語の原文を引用して、定義上の違いと繋がりを見てみましょう。
A Function Type is (roughly) a type of the form (T1, ..., Tn) => U, which is a shorthand for the trait FunctionN in the standard library. Anonymous Functions and Method Values have function types, and function types can be used as part of value, variable and function declarations and definitions. In fact, it can be part of a method type.
A Method Type is a non-value type. That means there is no value - no object, no instance - with a method type. As mentioned above, a Method Value actually has a Function Type. A method type is a def declaration - everything about a def except its body.
例子:
scala> def m1(x:Int) = x+3 m1: (x: Int)Int scala> val f1 = (x: Int) => x+3 f1: Int => Int = <function1>
見てください、メソッド定義と関数定義はScalaのパーサーのシグネチャーに表示されていますよね。def m1(x: Int) = x+3 は単純なメソッド定義です。シグネチャー中の m1: (x: Int)Int は、メソッド m1 が Int 型のパラメータ x を一つ持ち、戻り値が Int 型であることを示しています。
val f1 = (x: Int) => x+3 は関数の定義です。パーサーのシグネチャにおける f1: Int => Int = <function1> は、関数 f1 のメソッド本体が Int 型のパラメータを 1 つ受け取り、出力結果の型が Int 型であることを示しています。
上記の例から、まとめを導き出す:
メソッドは、defで始まり、引数リスト(引数リストなしでもよい)を持つ論理操作ブロックであり、これはobjectやclassのメンバーメソッドと同様です。
関数は、変数(または定数)に代入される匿名メソッド(パラメータリストの有無にかかわらず)であり、=>変換記号によって論理コードブロックに続く式です。=>変換記号の後の論理コードブロックの記述方法は、メソッドの本体部分と同じです。
其他区别
methodは式の一部として現れることができます(関数を呼び出して引数を渡す)が、method(引数を持つメソッド)は最終的な式になることはできません(引数なしのメソッドは可能ですが、これはメソッド呼び出しになります。なぜならscalaは引数なしのメソッド呼び出しで()の省略を許可しているからです)。一方、functionは最終的な式として現れることができます。
scala> m1
<console>:12: error: missing arguments for method m1;
follow this method with `_' if you want to treat it as a partially applied function
m1
^
scala> f1
res1: Int => Int = <function1>
methodはパラメータリストを持たないことも、パラメータリストが空であることもできます。しかし、functionはパラメータリストを持つ必要があります(空でも構いません)。メソッド名はメソッド呼び出しを意味し、関数名は単に関数自身を表します:
scala> def m2 = 100;
m2: Int
scala> def m3() = 1000;
m3: ()Int
scala> var f2 = => 100;
<console>:1: error: illegal start of simple expression
var f2 = => 100;
^
scala> var f2 =()=> 100;
f2: () => Int = <function0>
scala> m2
res2: Int = 100
scala> m3
res3: Int = 1000
scala> m3()
res4: Int = 1000
scala> f2
res5: () => Int = <function0>
scala> f2()
res6: Int = 100
関数が現れるべき場所では、メソッドを提供することができます。
これは、関数が期待される場所にメソッドを提供した場合、そのメソッドが自動的に関数に変換されるからです。この動作はETA expansionと呼ばれます。
注意:
関数が期待される場所では、メソッドを使用できます。
関数が期待されない場所では、メソッドは自動的に関数に変換されません。
scalaでは、演算子はメソッドとして解釈されます:
- 前置演算子:op obj は obj.op として解釈されます
- 中置演算子:obj1 op obj2 は obj1.op(obj2) として解釈される
- 後置演算子:obj op は obj.op として解釈されます
scala> val ml = List(1,2,3,4) ml: List[Int] = List(1, 2, 3, 4) scala> ml.map((x)=>2*x) res0: List[Int] = List(2, 4, 6, 8) scala> def m(x:Int) = 2*x m: (x: Int)Int scala> ml.map(m) res1: List[Int] = List(2, 4, 6, 8) scala> def m(x:Int) = 3*x m: (x: Int)Int scala> ml.map(m) res2: List[Int] = List(3, 6, 9, 12)
メソッド名の後ろにアンダースコアを付けることで、強制的に関数に変えることができます。
注意:メソッド名とアンダースコアの間には、少なくとも1つのスペースが必要ですよ!
scala> def m3(x: Int): Int = x * x * x
m3: (x: Int)Int
scala> val f3 = m3_
<console>:10: error: not found: value m3_
val f3 = m3_
^
scala> val f3 = m3 _
f3: Int => Int = <function1>
scala> f3(3)
res0: Int = 27
原文地址:https://www.cnblogs.com/shihuc/p/5082701.html