在我沒有學習scala的時候,主要用java和python做日常工作開發,印象中,沒有特別的刻意的去區分method和function的區別,這個關系,正如我們日常生活中,沒有刻意的去區分質量和重量。但是,他們之間,的確是有所不同的,這些不同也是建立在他們之間有聯系的基礎之上!
1. 如何定義
首先,還是引用英文原文來看看他們在定義上的區別和聯系吧:
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.
2. 具體例子分析
1 scala> def m1(x:Int) = x+3 2 m1: (x: Int)Int 3 4 scala> val f1 = (x: Int) => x+3 5 f1: Int => Int = <function1>
看到沒,方法定義和函數定義是不是在scala的解析器signature上就有顯示了,def m1(x: Int) = x+3就是一個簡單的method的定義。signature中m1: (x: Int)Int 表示method m1有一個參數Int型參數x,返回值是Int型。
val f1 = (x: Int) => x+3則是function的定義,解析器的signature中f1: Int => Int = <function1>表示function f1的method體接受一個Int型的參數,輸出結果的類型是Int型。
從上面的例子,得出一個總結:
方法是一個以def開頭的帶有參數列表(可以無參數列表)的一個邏輯操作塊,這正如object或者class中的成員方法一樣。
函數是一個賦值給一個變量(或者常量)的匿名方法(帶或者不帶參數列表),並且通過=>轉換符號跟上邏輯代碼塊的一個表達式。=>轉換符號后面的邏輯代碼塊的寫法與method的body部分相同。
3. 區別都還有那些?
method可以作為一個表達式的一部分出現(調用函數並傳參),但是method(帶參方法)不能作為最終的表達式(無參方法可以,但是這個就成了方法調用,因為scala允許無參方法調用時省略()括號),而function可以作為最終的表達式出現。 |
1 scala> m1 2 <console>:12: error: missing arguments for method m1; 3 follow this method with `_' if you want to treat it as a partially applied function 4 m1 5 ^ 6 7 scala> f1 8 res1: Int => Int = <function1>
method可以沒有參數列表,參數列表也可以為空。但是function必須有參數列表(也可以為空)。方法名意味着方法調用,函數名只是代表函數自身 |
1 scala> def m2 = 100; 2 m2: Int 3 4 scala> def m3() = 1000; 5 m3: ()Int 6 7 scala> var f2 = => 100; 8 <console>:1: error: illegal start of simple expression 9 var f2 = => 100; 10 ^ 11 12 scala> var f2 =()=> 100; 13 f2: () => Int = <function0>
1 scala> m2 2 res2: Int = 100 3 4 scala> m3 5 res3: Int = 1000 6 7 scala> m3() 8 res4: Int = 1000 9 10 scala> f2 11 res5: () => Int = <function0> 12 13 scala> f2() 14 res6: Int = 100
在函數出現的地方我們可以提供一個方法。 這是因為,如果期望出現函數的地方我們提供了一個方法的話,該方法就會自動被轉換成函數。該行為被稱為ETA expansion。 注意: 期望出現函數的地方,我們可以使用方法。 不期望出現函數的地方,方法並不會自動轉換成函數 在scala中操作符被解釋稱方法:
|
1 scala> val ml = List(1,2,3,4) 2 ml: List[Int] = List(1, 2, 3, 4) 3 4 scala> ml.map((x)=>2*x) 5 res0: List[Int] = List(2, 4, 6, 8) 6 7 scala> def m(x:Int) = 2*x 8 m: (x: Int)Int 9 10 scala> ml.map(m) 11 res1: List[Int] = List(2, 4, 6, 8) 12 13 scala> def m(x:Int) = 3*x 14 m: (x: Int)Int 15 16 scala> ml.map(m) 17 res2: List[Int] = List(3, 6, 9, 12)
可以在方法名后面加一個下划線強制變成函數。 注意: 方法名與下划線之間至少有一個空格喲! |
1 scala> def m3(x: Int): Int = x * x * x 2 m3: (x: Int)Int 3 4 scala> val f3 = m3_ 5 <console>:10: error: not found: value m3_ 6 val f3 = m3_ 7 ^ 8 9 scala> val f3 = m3 _ 10 f3: Int => Int = <function1> 11 12 scala> f3(3) 13 res0: Int = 27