Scala中的方法和函數的區別。

[英]Difference between method and function in Scala


I read Scala Functions (part of Another tour of Scala). In that post he stated:

我閱讀了Scala函數(Scala的另一篇教程)。在這篇文章中,他說:

Methods and functions are not the same thing

方法和函數不是一回事。

But he didn't explain anything about it. What was he trying to say?

但是他沒有解釋。他想說什么?

6 个解决方案

#1


207  

Jim has got this pretty much covered in his blog post, but I'm posting a briefing here for reference.

Jim在他的博客文章中已經提到了這一點,但是我在這里發布了一個簡報以供參考。

First, let's see what the Scala Specification tell us. Chapter 3 (types) tell us about Function Types (3.2.9) and Method Types (3.3.1). Chapter 4 (basic declarations) speaks of Value Declaration and Definitions (4.1), Variable Declaration and Definitions (4.2) and Functions Declarations and Definitions (4.6). Chapter 6 (expressions) speaks of Anonymous Functions (6.23) and Method Values (6.7). Curiously, function values is spoken of one time on 3.2.9, and no where else.

首先,讓我們看看Scala規范告訴我們什么。第3章(類型)告訴我們函數類型(3.2.9)和方法類型(3.3.1)。第4章(基本聲明)談到價值聲明和定義(4.1)、變量聲明和定義(4.2)和函數聲明和定義(4.6)。第6章(表達式)討論匿名函數(6.23)和方法值(6.7)。奇怪的是,函數值是在3.2.9上說的,而不是在其他地方。

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.

函數類型(大致)是表單的類型(T1,…,Tn) => U,這是標准庫中trait FunctionN的簡寫。匿名函數和方法值具有函數類型,函數類型可以作為值、變量和函數聲明和定義的一部分。實際上,它可以是方法類型的一部分。

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.

方法類型是非值類型。這意味着沒有任何值——沒有對象,沒有實例——使用方法類型。如上所述,方法值實際上有一個函數類型。一個方法類型是一個def聲明——除了它的主體之外的所有定義。

Value Declarations and Definitions and Variable Declarations and Definitions are val and var declarations, including both type and value - which can be, respectively, Function Type and Anonymous Functions or Method Values. Note that, on the JVM, these (method values) are implemented with what Java calls "methods".

值聲明和定義和變量聲明和定義是val和var聲明,包括類型和值,它們分別可以是函數類型和匿名函數或方法值。注意,在JVM上,這些(方法值)是用Java調用的“方法”實現的。

A Function Declaration is a def declaration, including type and body. The type part is the Method Type, and the body is an expression or a block. This is also implemented on the JVM with what Java calls "methods".

函數聲明是一個def聲明,包括類型和主體。類型部分是方法類型,而主體是一個表達式或塊。這也是用Java調用的“方法”在JVM上實現的。

Finally, an Anonymous Function is an instance of a Function Type (ie, an instance of the trait FunctionN), and a Method Value is the same thing! The distinction is that a Method Value is created from methods, either by postfixing an underscore (m _ is a method value corresponding to the "function declaration" (def) m), or by a process called eta-expansion, which is like an automatic cast from method to function.

最后,一個匿名函數是一個函數類型的實例(例如,trait FunctionN的實例),方法值也是一樣的!區別在於方法值是由方法創建的,或者通過postfix一個下划線(m_是一個與“函數聲明”(def) m相對應的方法值),或者通過一個稱為“eta-展開”的過程,這就像一個自動的從方法到函數的轉換。

That is what the specs say, so let me put this up-front: we do not use that terminology! It leads to too much confusion between so-called "function declaration", which is a part of the program (chapter 4 -- basic declarations) and "anonymous function", which is an expression, and "function type", which is, well a type -- a trait.

這就是規格說明的內容,所以讓我把它放在前面:我們不使用這個術語!它導致了所謂的“函數聲明”之間的混淆,這是程序的一部分(第4章——基本聲明)和“匿名函數”,這是一個表達式,“函數類型”,也就是一種類型——一種特性。

The terminology below, and used by experienced Scala programmers, makes one change from the terminology of the specification: instead of saying function declaration, we say method. Or even method declaration. Furthermore, we note that value declarations and variable declarations are also methods for practical purposes.

下面的術語,由經驗豐富的Scala程序員使用,從規范的術語變成了一個變化:我們說的不是函數聲明,而是方法。甚至方法聲明。此外,我們注意到,價值聲明和變量聲明也是用於實際目的的方法。

So, given the above change in terminology, here's a practical explanation of the distinction.

因此,考慮到上述術語的變化,這里有一個關於區別的實用解釋。

A function is an object that includes one of the FunctionX traits, such as Function0, Function1, Function2, etc. It might be including PartialFunction as well, which actually extends Function1.

一個函數是一個對象,它包含一個FunctionX特性,比如Function0, Function1, Function2,等等。它可能包括PartialFunction,它實際上擴展了Function1。

Let's see the type signature for one of these traits:

讓我們看看其中一個特征的類型簽名:

trait Function2[-T1, -T2, +R] extends AnyRef

This trait has one abstract method (it has a few concrete methods as well):

這種特性有一個抽象的方法(它也有一些具體的方法):

def apply(v1: T1, v2: T2): R

And that tell us all that there is to know about it. A function has an apply method which receives N parameters of types T1, T2, ..., TN, and returns something of type R. It is contra-variant on the parameters it receives, and co-variant on the result.

這告訴了我們所有關於它的信息。一個函數有一個應用方法,它接收了T1、T2、……,TN,並返回某種類型的r,它是對其接收的參數的反向變量,並對結果進行協變。

That variance means that a Function1[Seq[T], String] is a subtype of Function1[List[T], AnyRef]. Being a subtype means it can be used in place of it. One can easily see that if I'm going to call f(List(1, 2, 3)) and expect an AnyRef back, either of the two types above would work.

這個方差意味着Function1[Seq[T], String]是Function1[List[T], AnyRef]的子類型。作為一個亞型意味着它可以被用來代替它。可以很容易地看到,如果我要調用f(List(1, 2, 3))並期望一個AnyRef返回,上述兩種類型中的任何一個都可以工作。

Now, what is the similarity of a method and a function? Well, if f is a function and m is a method local to the scope, then both can be called like this:

方法和函數的相似性是什么?如果f是一個函數m是作用域的一個方法,那么兩者都可以這樣命名:

val o1 = f(List(1, 2, 3))
val o2 = m(List(1, 2, 3))

These calls are actually different, because the first one is just a syntactic sugar. Scala expands it to:

這些調用實際上是不同的,因為第一個是語法糖。Scala擴展它:

val o1 = f.apply(List(1, 2, 3))

Which, of course, is a method call on object f. Functions also have other syntactic sugars to its advantage: function literals (two of them, actually) and (T1, T2) => R type signatures. For example:

當然,這是一個對象f的方法調用。函數也有其他語法糖的優點:函數字面量(實際上是兩個)和(T1, T2) => R類型的簽名。例如:

val f = (l: List[Int]) => l mkString ""
val g: (AnyVal) => String = {
  case i: Int => "Int"
  case d: Double => "Double"
  case o => "Other"
}

Another similarity between a method and a function is that the former can be easily converted into the latter:

方法和函數之間的另一個相似之處是前者可以很容易地轉換成后者:

val f = m _

Scala will expand that, assuming m type is (List[Int])AnyRef into (Scala 2.7):

如果m類型是(List[Int])AnyRef (Scala 2.7), Scala將擴展它:

val f = new AnyRef with Function1[List[Int], AnyRef] {
  def apply(x$1: List[Int]) = this.m(x$1)
}

On Scala 2.8, it actually uses an AbstractFunction1 class to reduce class sizes.

在Scala 2.8中,它實際上使用AbstractFunction1類來減少類大小。

Notice that one can't convert the other way around -- from a function to a method.

請注意,不能將另一種方法從函數轉換為方法。

Methods, however, have one big advantage (well, two -- they can be slightly faster): they can receive type parameters. For instance, while f above can necessarily specify the type of List it receives (List[Int] in the example), m can parameterize it:

但是,方法有一個很大的優勢(嗯,兩個——它們可以稍微快一點):它們可以接收類型參數。例如,如果上面的f可以指定它所接收的列表的類型(列表[Int]),那么m可以將其參數化:

def m[T](l: List[T]): String = l mkString ""

I think this pretty much covers everything, but I'll be happy to complement this with answers to any questions that may remain.

我認為這幾乎涵蓋了所有的問題,但我很樂意回答任何可能存在的問題。

#2


62  

One big practical difference between a method and a function is what return means. return only ever returns from a method. For example:

方法和函數之間的一個很大的實際差別是返回的含義。返回僅從方法返回。例如:

scala> val f = () => { return "test" }
<console>:4: error: return outside method definition
       val f = () => { return "test" }
                       ^

Returning from a function defined in a method does a non-local return:

從方法中定義的函數返回非本地返回:

scala> def f: String = {                 
     |    val g = () => { return "test" }
     | g()                               
     | "not this"
     | }
f: String

scala> f
res4: String = test

Whereas returning from a local method only returns from that method.

而從本地方法返回只返回該方法。

scala> def f2: String = {         
     | def g(): String = { return "test" }
     | g()
     | "is this"
     | }
f2: String

scala> f2
res5: String = is this

#3


30  

function A function can be invoked with a list of arguments to produce a result. A function has a parameter list, a body, and a result type. Functions that are members of a class, trait, or singleton object are called methods. Functions defined inside other functions are called local functions. Functions with the result type of Unit are called procedures. Anonymous functions in source code are called function literals. At run time, function literals are instantiated into objects called function values.

函數可以用一個參數列表來調用,以生成結果。函數有一個參數列表、一個主體和一個結果類型。屬於類、trait或singleton對象的函數稱為方法。在其他函數中定義的函數稱為局部函數。函數與結果類型的單元稱為過程。在源代碼中的匿名函數稱為函數文字。在運行時,函數文本被實例化到稱為函數值的對象中。

Programming in Scala Second Edition. Martin Odersky - Lex Spoon - Bill Venners

Scala第二版編程。馬丁·奧德斯基-萊科斯-比爾·凡納斯。

#4


26  

Let Say you have a List

假設你有一個清單。

scala> val x =List.range(10,20)
x: List[Int] = List(10, 11, 12, 13, 14, 15, 16, 17, 18, 19)

Define a Method

定義一個方法

scala> def m1(i:Int)=i+2
m1: (i: Int)Int

Define a Function

定義一個函數

scala> (i:Int)=>i+2
res0: Int => Int = <function1>

scala> x.map((x)=>x+2)
res2: List[Int] = List(12, 13, 14, 15, 16, 17, 18, 19, 20, 21)

Method Accepting Argument

方法接受參數

scala> m1(2)
res3: Int = 4

Defining Function with val

定義函數與瓦爾

scala> val p =(i:Int)=>i+2
p: Int => Int = <function1>

Argument to function is Optional

函數的參數是可選的。

 scala> p(2)
    res4: Int = 4

scala> p
res5: Int => Int = <function1>

Argument to Method is Mandatory

對方法的論證是強制性的。

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

Check the following Tutorial that explains passing other differences with examples like other example of diff with Method Vs Function, Using function as Variables, creating function that returned function

請查看下面的教程,該教程解釋了如何使用方法Vs函數,使用函數作為變量,創建返回函數的函數的例子。

#5


11  

Functions don't support parameter defaults. Methods do. Converting from a method to a function loses parameter defaults. (Scala 2.8.1)

函數不支持參數默認值。做的方法。從方法轉換為函數會丟失參數默認值。(Scala 2.8.1發布)

#6


1  

There is a nice article here from which most of my descriptions are taken. Just a short comparison of Functions and Methods regarding my understanding. Hope it helps:

這里有一篇不錯的文章,我的大部分描述都是在這里進行的。只是簡單地比較一下我的理解的功能和方法。希望它可以幫助:

Functions: They are basically an object. More precisely, functions are objects with an apply method; Therefore, they are a little bit slower than methods because of their overhead. It is similar to static methods in the sense that they are independent of an object to be invoked. A simple example of a function is just like bellow:

功能:它們基本上是一個對象。更准確地說,函數是具有應用方法的對象;因此,它們比方法要慢一些,因為它們的開銷。它與靜態方法類似,因為它們獨立於被調用的對象。一個簡單的函數例子就像bellow:

val f1 = (x: Int) => x + x
f1(2)  // 4

The line above is nothing except assigning one object to another like object1 = object2. Actually the object2 in our example is an anonymous function and the left side gets the type of an object because of that. Therefore, now f1 is an object(Function). The anonymous function is actually an instance of Function1[Int, Int] that means a function with 1 parameter of type Int and return value of type Int. Calling f1 without the arguments will give us the signature of the anonymous function (Int => Int = )

除了將一個對象分配給object1 = object2之外,上面的行是沒有意義的。實際上,在我們的例子中,object2是一個匿名函數,而左邊得到的是對象的類型。因此,現在f1是一個對象(函數)。這個匿名函數實際上是Function1[Int, Int]的一個實例,它的意思是一個具有一個Int類型的參數和Int類型的返回值的函數。

Methods: They are not objects but assigned to an instance of a class,i.e., an object. Exactly the same as method in java or member functions in c++ (as Raffi Khatchadourian pointed out in a comment to this question) and etc. A simple example of a method is just like bellow:

方法:它們不是對象,而是分配給類的實例,即。,一個對象。與java中的方法或c++中的成員函數完全相同(正如Raffi Khatchadourian在對這個問題的注釋中所指出的)等。一個簡單的方法示例就像bellow:

def m1(x: Int) = x + x
m1(2)  // 4

The line above is not a simple value assignment but a definition of a method. When you invoke this method with the value 2 like the second line, the x is substituted with 2 and the result will be calculated and you get 4 as an output. Here you will get an error if just simply write m1 because it is method and need the input value. By using _ you can assign a method to a function like bellow:

上面的行不是一個簡單的值分配,而是一個方法的定義。當你用值2來調用這個方法,比如第二行,用2代替x,結果會計算出來,得到4作為輸出。如果只是簡單地寫m1,就會得到一個錯誤,因為它是方法,需要輸入值。通過使用_,您可以將一個方法分配給如下函數:

val f2 = m1 _  // Int => Int = <function1>

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2010/03/27/6b4972de25e215c4d94a733d0afc6118.html



 
  © 2014-2022 ITdaan.com 联系我们: