Scala:由于JVM的限制,方法不是函数?

agyaoht7  于 6个月前  发布在  Scala
关注(0)|答案(2)|浏览(113)

我发现经常有人提到在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限制到底是什么呢?

wljmcqd8

wljmcqd81#

我发现经常有人提到,在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-expansion”,只有在类型已知时才由编译器完成,如上面的第三个val g示例或list.map(f)示例。
现在,如果您期望g方法f的别名,那么这是不可能的。
因为g是一个,而在语言中方法不是
这可能是由于JVM的限制,但最终只是创建者做出的设计选择。
我不知道为什么Scala不能只使用函数对象。
因为,最初,在Scala 2中,方法比函数更强大。
例如,函数不能有类型参数,不能接收implicit值,不能重载,等等。

Scala 3创建了一系列特性来减少这些限制,比如上下文函数 A ?=> B 和类型类型 [X] =>> F[X]。但是方法仍然有一些独特的东西,比如重载。

此外,由于JVM的工作方式,无论如何都需要方法。因为在一天结束时,函数只是一个对象/值,并附加了一个apply方法
还有性能参数,因为如果我们只有函数,那么会有很多间接,最终必须在运行时调用方法
说了这么多,理论上,语言可以抽象所有这些内部细节,只有函数,使函数特殊,编译器可以将大多数东西内联到类中的方法等等。
然而,不这样做的原因可能有很多。我不知道真实的原因,但我可以想象一些似是而非的原因,比如:

  • 生成的代码可能会更慢且浪费。
  • 编译器的额外工作。在这个意义上,它会更慢,更难维护。
  • 更难与其他JVM语言(如Java*)互操作(这在早期的Scala**时代是一个很大的禁忌,当时没有那么多的本地库)*。
4xy9mtcn

4xy9mtcn2#

JVM中没有“函数”,只有方法。

trait Function1[In, Out] {
   def apply(in: In): Out
}

字符串
现在,在你的例子中,为什么编译器拒绝将一个方法转换成一个函数--这只是因为scala社区的某个有权势的人认为它不应该这样做。我不认为这是一个合理的原因,而且这绝对不是因为任何JVM的限制。(我可能错了,但我认为scala的早期版本曾经允许这些转换,只是后来被删除了)。

相关问题