答案 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