Scala中方法和函数之间的区别

时间:2010-03-27 12:06:17

标签: function scala methods

我读了 Scala Functions 另一个Scala之旅的一部分)。在那篇文章中他说:

  

方法和功能不是一回事

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

9 个答案:

答案 0 :(得分:224)

答案 1 :(得分:65)

方法和函数之间的一个重大实际区别是return的含义。 return只能从方法返回。例如:

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

从方法中定义的函数返回非本地返回:

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

scala> f
res4: String = test

而从本地方法返回只从该方法返回。

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

scala> f2
res5: String = is this

答案 2 :(得分:34)

  

function 可以使用参数列表调用函数以生成a   结果。函数具有参数列表,正文和结果类型。   作为类,特征或单例对象的成员的函数是   称为方法。调用其他函数中定义的函数   地方职能。结果类型为Unit的函数称为过程。   源代码中的匿名函数称为函数文字。   在运行时,函数文字被实例化为被调用的对象   功能值。

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

答案 3 :(得分:29)

假设您有一个列表

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

定义方法

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

定义一个函数

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)

接受参数的方法

scala> m1(2)
res3: Int = 4

用val

定义函数
scala> val p =(i:Int)=>i+2
p: Int => Int = <function1>

功能参数是可选的

 scala> p(2)
    res4: Int = 4

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

方法的争论是强制性的

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

检查以下Tutorial,解释通过其他示例传递其他差异,例如使用方法Vs函数的diff的其他示例,使用函数作为变量,创建返回函数的函数

答案 4 :(得分:12)

函数不支持参数默认值。方法呢。从方法转换为函数会丢失参数默认值。 (Scala 2.8.1)

答案 5 :(得分:6)

有一篇很好的文章here,我的大部分描述都来自这篇文章。 只是简单比较一下我的理解的功能和方法。希望它有所帮助:

<强>功能: 它们基本上是一个对象。更准确地说,函数是具有apply方法的对象;因此,由于它们的开销,它们比方法慢一点。它类似于静态方法,因为它们独立于要调用的对象。 一个简单的函数示例就像下面这样:

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

除了将一个对象分配给另一个对象(如object1 = object2)之外,上面的行都没有。实际上,我们示例中的object2是一个匿名函数,左侧因此得到了一个对象的类型。因此,现在f1是一个对象(Function)。匿名函数实际上是Function1 [Int,Int]的一个实例,它表示一个函数,其中一个参数类型为Int,返回值类型为Int。 在没有参数的情况下调用f1将为我们提供匿名函数的签名(Int =&gt; Int =)

<强>方法: 它们不是对象,而是分配给类的实例,即对象。与java中的方法或c ++中的成员函数完全相同(在Raffi Khatchadourian的注释中指出为this question)等。 一个简单的方法示例就像下面这样:

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

上面的行不是简单的值赋值,而是方法的定义。当您使用值2调用此方法时,如第二行,x将替换为2,结果将被计算,您将获得4作为输出。如果只是简单地编写m1就会出现错误,因为它是方法并且需要输入值。通过使用_,您可以将方法分配给类似下面的函数:

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

答案 6 :(得分:1)

在Scala 2.13中,与函数不同,方法可以采用/返回

  • 类型参数(多态方法)
  • 隐式参数
  • 依赖类型

但是,Polymorphic function types #4672在dotty(Scala 3)中取消了这些限制,例如,dotty版本0.23.0-RC1启用了following syntax

类型参数

def fmet[T](x: List[T]) = x.map(e => (e, e))
val ffun = [T] => (x: List[T]) => x.map(e => (e, e))

隐含参数(context个参数)

def gmet[T](implicit num: Numeric[T]): T = num.zero
val gfun: [T] => Numeric[T] ?=> T = [T] => (using num: Numeric[T]) => num.zero

从属类型

class A { class B }
def hmet(a: A): a.B = new a.B
val hfun: (a: A) => a.B = hmet

有关更多示例,请参见tests/run/polymorphic-functions.scala

答案 7 :(得分:1)

实际上,Scala程序员只需知道以下三个规则即可正确使用函数和方法:

  • =>定义的方法和由someNumber.foreach(println)定义的函数文字是函数。在《 Scala编程》(第4版)的第8章第143页中对此进行了定义。
  • 函数值是可以作为任何值传递的对象。函数文字和部分应用的函数是函数值。
  • 如果在代码中的某个点需要函数值,则可以省略部分应用的函数的下划线。例如:background

在Scala编程的四个版本之后,人们仍然需要区分两个重要的概念:函数和函数值,因为所有版本都没有给出清晰的解释。语言规范太复杂。我发现上述规则简单准确。

答案 8 :(得分:0)

这是Rob Norris出色的post,解释了区别,这里是TL; DR

  

Scala中的方法不是值,而函数是值。您可以构造一个函数,该函数通过η-expansion(由结尾的下划线thingy触发)来委托给方法。

具有以下定义:

  

方法是用 def 定义的,而是可以分配给 val < / p>

简而言之(从博客中提取):

定义方法时,我们发现无法将其分配给val

scala> def add1(n: Int): Int = n + 1
add1: (n: Int)Int

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

还要注意add1类型,这看起来不正常;您不能声明类型为(n: Int)Int的变量。方法不是值。

但是,通过添加η-扩展后缀运算符(η表示为“ eta”),我们可以将方法转换为函数值。请注意f的类型。

scala> val f = add1 _
f: Int => Int = <function1>

scala> f(3)
res0: Int = 4

_的作用等同于执行以下操作:我们构造了一个Function1实例,该实例委托给我们的方法。

scala> val g = new Function1[Int, Int] { def apply(n: Int): Int = add1(n) }
g: Int => Int = <function1>

scala> g(3)
res18: Int = 4