Scala中方法和函数的区别 [英] Difference between method and function in Scala

查看:107
本文介绍了Scala中方法和函数的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我阅读 Scala Functions 的一部分) > Scala的另一次旅程)。他在那篇文章中表示:


方法和函数不是同一件事

但他没有解释任何事情。他想说什么?

解决方案

Jim已经在他的博客文章,但我在这里发布简报以供参考。



首先,让我们看看Scala规范告诉我们什么。第3章(类型)告诉我们有关函数类型(3.2.9)和方法类型(3.3.1)。第4章(基本声明)提到了<价值声明和定义(4.1),变量声明和定义(4.2)和函数声明和定义 4.6)。第6章(表达式)提到匿名函数(6.23)和方法值(6.7)。奇怪的是,函数值在3.2.9上只说了一次,没有其他地方。



一个函数类型(大体上)是一个类型形式为(T1,...,Tn)=> U ,它是标准库中特征 FunctionN 的缩写。 匿名函数方法值具有函数类型,函数类型可用作值,变量和函数声明和定义的一部分。实际上,它可以是方法类型的一部分。


$ b 方法类型是一个 非值类型 即可。这意味着存在 no 值 - 没有对象,没有实例 - 带有方法类型。如上所述,方法值实际上具有功能类型。方法类型是一个 def 声明 - 除了它的主体外,关于 def 的所有内容。



价值声明和定义变量声明和定义 val var 声明,包括类型和值 - 可分别为函数类型匿名函数或方法值即可。请注意,在JVM上,这些(方法值)由Java调用方法实现。


$ b

函数声明 def 声明,包括 type body 。类型部分是方法类型,而主体是表达式或块。这也是在JVM上用Java调用方法实现的。

最后,一个匿名函数是一个函数类型(即特征 FunctionN )的实例和方法值是同一件事!区别在于方法值是通过方法创建的,或者通过后缀下划线( m _ 是与函数声明相对应的方法值( def m ),或者使用名为 eta-expansion 的进程,以便运作。



规格说明就是这样,所以让我先说一下:我们不使用该术语!在所谓的函数声明(它是程序的一部分(第4章 - 基本声明)和匿名函数)之间存在太多的混淆,一个表达式和函数类型,它就是一个类型 - 一个特征。 下面的术语,由有经验的人使用Scala程序员对规范的术语做了一个改变:而不是函数声明,我们说方法 。甚至方法声明。此外,我们注意到值声明变量声明也是实际使用的方法。
$ b ,鉴于上述术语的变化,下面是对这种区别的实际解释。



函数是一个对象,它包含一个 FunctionX 特征,例如 Function0 Function1 Function2 等等,它可能也包括 PartialFunction ,它实际上扩展了 Function1 <

让我们来看看这些特征之一的类型签名:

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

trait有一个抽象方法(它也有一些具体方法):

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

这告诉我们所有人都知道这件事。一个函数有一个 apply 方法,它接收类型为 T1 > T2 ,..., TN ,并返回 R 类型的内容。它在它接收的参数上是相反的变体,并且在结果上是共变的。

这个变量意味着一个 Function1 [Seq [T ],String] Function1 [List [T],AnyRef] 的子类型。作为一个子类型意味着它可以用替代它。我们可以很容易地看到,如果我要调用 f(List(1,2,3))并期望 AnyRef 返回,以上两种类型中的任何一种都可以工作。



现在,方法和函数的相似度是什么?那么,如果 f 是一个函数, m 是作用域本地的方法,那么两者都可以像这样调用:

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

这些调用实际上是不同的,因为第一个只是一个语法糖。 Scala将它扩展为:
$ b $ pre $ val $ o $ = f.apply(List(1,2,3))

当然,这是一个调用对象 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 => 其他
}

方法和函数之间的另一个相似之处在于前者可以轻松转换为后者:

  val f = m _ 
m
类型为,那么Scala会展开 (List [Int])AnyRef into(Scala 2.7):

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

在Scala 2.8中,它实际上使用 AbstractFunction1 类来减少类的大小。 b
$ b

请注意,不能将其他方式转换 - 从函数转换为方法。

然而,方法有一个很大的优势(好吧,两个 - 它们可以稍快一点):它们可以接收类型参数。例如,上面的 f 可以指定 List 的类型( List [在这个例子中), m 可以参数化:

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

我认为这几乎涵盖了所有内容,但我很乐意补充这一点,并回答任何可能存在的问题。


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

Methods and functions are not the same thing

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

解决方案

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

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.

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.

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".

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".

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.

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.

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.

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.

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.

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.

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:

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:

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:

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):

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.

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:

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.

这篇关于Scala中方法和函数的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆