我发现在 Scala 中经常提到类似的尝试
def f(x: Int): Int = x*x
val g = f // note the missing type
这是不可能的,因为“JVM 如何处理方法的潜在限制”。
error: missing argument list for method f
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `f _` or `f(_)` instead of `f`.
还是以下
List[Int](1, 2, 3, 4).map(f)
确实有效。当然,
map
中需要一个函数。但这很令人惊讶,因为我没有看到 g = f
中的歧义。 f
是一个单一参数的方法,f
不能是简单的调用。
还有 while 方法和函数对象,定义如下
val ff: Int => Int = x => x*x
在 Scala 中不一样,我不知道为什么 Scala 不能只拥有函数对象。
那么导致这些怪癖的 JVM 限制到底是什么?
我发现在 Scala 中经常提到类似的尝试
def f(x: Int): Int = x*x val g = f
这是不可能的,因为“JVM 如何处理方法的潜在限制”。
嗯,这取决于您到底期望
g
是什么?
如果您希望它只是一个调用 f
的函数,那么做起来非常简单,您只需要多一点语法即可:
// All these three work.
val g = (x: Int) => f(x)
val g = f(_)
val g: Int => Int = f
从方法创建函数自动称为“eta扩展”,并且仅在类型已知时由编译器完成,如上面的第三个
val g
示例或在list.map(f)
情况中.
现在,如果您期望
g
是 方法 f
的别名,那么这是不可能的。g
是一个 值,并且在语言中 方法 不是 值。
这可能是由于 JVM 的限制,但最终只是创建者所做的设计选择。
我不知道为什么 Scala 不能只拥有函数对象。
因为,最初,在 Scala 2 中,方法比函数更强大。
例如,函数不能有类型参数、不能接收
implicit
值、不能重载等等
Scala 3 创建了一系列功能来减少这些限制,例如上下文函数 (
A ?=> B
) 和 lambda 类型([X] =>> F[X]
)。但方法仍然有一些独特的东西,比如重载。
此外,由于 JVM 的工作方式,您无论如何都需要方法。因为归根结底,函数只是一个对象/值,附加了
apply
方法。
还有性能参数,因为如果我们只有函数,那么就会有很多间接,最终不得不在运行时调用方法。
话虽如此,理论上,该语言可以抽象出所有这些内部细节,只具有函数,使函数变得特殊,并且编译器可以将大多数内容内联到类中的方法等等。
但是,不这样做可能有很多原因。我不知道真实的,但我可以想象一些看似合理的: