为什么函数是值而方法不是,或者是什么让函数成为值?什么可以让我破译方法不包含该特征?
最佳答案
Scala 是一种面向对象的语言。在面向对象语言中,每个值都是一个对象,每个对象也是一个值。
方法绑定(bind)到对象。让方法同时成为对象的构建 block 和对象本身是很尴尬的。让它们不成为对象会更容易。
从某种意义上说,Scala 中的函数只是一个具有 apply
方法的对象。如果范围内没有名为 foo
的方法,则 foo()
is simply syntactic sugar for foo.apply()
。因此,函数之所以是值,是因为它们是对象。
虽然任何具有 apply
方法的对象都可以像函数一样被调用,但当我们在 Scala 中谈论“函数”时,我们通常意味着更多的东西具体: FunctionN
之一的实例特征如Function2[-T1, -T2, +R]
。特别是,函数文字语法
val add = (a: Int, b: Int) => a + b
val add = new Function2[Int, Int, Int] {
override def apply(a: Int, b: Int) = a + b
}
type F = (Int, String, Long) => Boolean
是
的语法糖type F = Function3[Int, String, Long, Boolean]
其中每个 FunctionN
特征的定义如下:
package scala
trait Function0[+R] {
def apply: R
override def toString = "<function>"
}
trait Function1[-T, +R] {
def apply(x: T): R
override def toString = "<function>"
}
trait Function2[-T1, -T2, +R] {
def apply(x1: T1, x2: T2): R
override def toString = "<function>"
}
trait Function3[-T1, -T2, -T3, +R] {
def apply(x1: T1, x2: T2, x3: T3): R
override def toString = "<function>"
}
等等。
可以convert a method into a function value使用η-expansion 。这可以使用尾随下划线显式完成:
val f = println _
或者在某些情况下,当很明显需要函数值时,即使只使用方法的裸名称:
val it = Iterable(1, 2, 3)
it.foreach(println)
请注意,这与其他语言没有太大区别。例如,在 Java、C# 和 Ruby 中,情况是一样的:方法被定义为类(或 C# 中的结构和 Ruby 中的模块)的一部分,并且绑定(bind)到对象,但它们本身并不是对象。相反,您有一个单独的函数概念(Java 中的 SAM 接口(interface)/功能接口(interface)实例、C# 中的 Action
或 Func
、Proc
在 Ruby 中),它是一个对象。
在 Ruby 中,您可以为绑定(bind)到与 Proc
具有相同接口(interface)的对象的方法创建代理对象。
其他语言做出了不同的选择,即在 ECMAScript 和 Python 中,方法是对象/值,但它们不像 Scala、Java、C# 和 Ruby 那样与对象紧密绑定(bind)。相反,方法基本上是分配给对象字段的普通函数。
关于scala - 为什么函数是值,而方法 id 不是?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62252045/