我发现经常有人提到在Scala 2中,
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`.
型
我看不出g = f
中的歧义。f
是一个带有单个参数的方法,f
不可能是一个简单的调用。
而方法和函数对象,定义为
val ff: Int => Int = x => x*x
型
Scala中的函数对象是不一样的,我不知道为什么Scala不能只使用函数对象。
那么,导致这些怪癖的JVM限制到底是什么呢?
2条答案
按热度按时间wljmcqd81#
我发现经常有人提到,在Scala中,
字符串
是不可能的,因为“JVM处理方法的潜在限制”。
嗯,这取决于你到底希望
g
是什么?如果你想让它只是一个调用f
的函数,那么这很简单,你只需要多一点语法:型
从方法中自动创建函数被称为 “eta-expansion”,只有在类型已知时才由编译器完成,如上面的第三个
val g
示例或list.map(f)
示例。现在,如果您期望
g
是方法f
的别名,那么这是不可能的。因为
g
是一个值,而在语言中方法不是值。这可能是由于JVM的限制,但最终只是创建者做出的设计选择。
我不知道为什么Scala不能只使用函数对象。
因为,最初,在Scala 2中,方法比函数更强大。
例如,函数不能有类型参数,不能接收
implicit
值,不能重载,等等。Scala 3创建了一系列特性来减少这些限制,比如上下文函数 (
A ?=> B
) 和类型类型 ([X] =>> F[X]
)。但是方法仍然有一些独特的东西,比如重载。此外,由于JVM的工作方式,无论如何都需要方法。因为在一天结束时,函数只是一个对象/值,并附加了一个
apply
方法。还有性能参数,因为如果我们只有函数,那么会有很多间接,最终必须在运行时调用方法。
说了这么多,理论上,语言可以抽象所有这些内部细节,只有函数,使函数特殊,编译器可以将大多数东西内联到类中的方法等等。
然而,不这样做的原因可能有很多。我不知道真实的原因,但我可以想象一些似是而非的原因,比如:
4xy9mtcn2#
JVM中没有“函数”,只有方法。
字符串
现在,在你的例子中,为什么编译器拒绝将一个方法转换成一个函数--这只是因为scala社区的某个有权势的人认为它不应该这样做。我不认为这是一个合理的原因,而且这绝对不是因为任何JVM的限制。(我可能错了,但我认为scala的早期版本曾经允许这些转换,只是后来被删除了)。