scala - 一个函数如何是一个值,而一个方法 ID 不是?
问题描述
为什么函数是值而方法不是,或者是什么使函数特别成为值?什么可以让我破译方法不包含该特征?
解决方案
Scala 是一种面向对象的语言。在面向对象的语言中,每个值都是一个对象,每个对象都是一个值。
方法绑定到对象。让方法既是对象的构建块又是对象本身是很尴尬的。让它们不是对象更容易。
在某种意义上,Scala 中的函数只是一个带有apply
方法的对象。如果没有foo
在作用域中命名的方法,那么foo()
就是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>"
}
等等。
可以使用η-expansion将方法转换为函数值。这可以使用尾随下划线显式完成:
val f = println _
或者在某些情况下,当很明显需要一个函数值时,即使只使用方法的裸名:
val it = Iterable(1, 2, 3)
it.foreach(println)
请注意,这与其他语言没有太大区别。例如,在 Java、C# 和 Ruby 中,它是相同的:方法被定义为类(或 C# 中的结构和 Ruby 中的模块)的一部分,并且绑定到对象,但不是对象本身。相反,您有一个单独的函数概念(Java 中的 SAM 接口/功能接口的实例,Action
或Func
C#Proc
中的 Ruby 中的函数接口),它是一个对象。
在 Ruby 中,您可以为绑定到具有相同接口的对象的方法创建代理对象Proc
。
其他语言做出不同的选择,即在 ECMAScript 和 Python 中,方法是对象/值,但它们不像在 Scala、Java、C# 和 Ruby 中那样与对象紧密绑定。相反,方法基本上是分配给对象字段的普通函数。
推荐阅读
- python - 将自定义操作按钮添加到用户列表页面,使员工能够通过单击按钮将用户设置为活动或非活动
- javascript - 使用“aweCheckbox”的多个下拉菜单效果很好,但是当想要设置“其他”选项时相关的 jquery 不适用于复选框检查取消选中
- c# - 模拟 url 在单元测试中调用
- r - `stringr::str_replace()` 用于列表或替换——但只返回一个输出
- jquery - 为什么单击按钮时我的局部视图没有呈现?
- javascript - 你如何用 JavaScript for VueJS 计算今天的日期?
- c# - c#asp.net动态生成按钮
- cron - 无法运行打开终端窗口的 cron 作业
- jenkins - 詹金斯构建中的空csv
- python - 有没有一种方法可以轻松地将 2 个索引之间的所有元素放入 Python 中的嵌套列表中?