为什么 Scala class 方法不是 first-class 公民?
Why are Scala class methods not first-class citizens?
我刚刚开始使用 Scala,正在修改工作表。例如:
def merp(str: String) : String = s"Merrrrrrrp $str"
val merp2 = (str: String) => s"Merrrrrrrp $str"
val merp3 = (str: String) => merp(str)
val merp4 = merp _
merp("rjkghleghe")
merp4("rjkghleghe")
以及相应的工作表结果:
merp: merp[](val str: String) => String
merp2: String => String = <function1>
merp3: String => String = <function1>
merp4: String => String = <function1>
res0: String = Merrrrrrrp rjkghleghe
res1: String = Merrrrrrrp rjkghleghe
例如,说 val merp5 = merp
会产生错误,因为显然方法不能像函数那样作为值。但我仍然可以将方法作为参数传递。我在以下代码片段中对此进行了演示,改编自 a similar SO question:
def intCombiner(a: Int, b: Int) : String = s"herrrrrrp $a derrrrrrp $b"
def etaAbstractor[A, B](combineFoo: (A, B) ⇒ String, a: A, b: B) = combineFoo(a, b)
etaAbstractor(intCombiner, 15, 16)
工作表结果:
intCombiner: intCombiner[](val a: Int,val b: Int) => String
etaAbstractor: etaAbstractor[A,B](val combineFoo: (A, B) => String,val a: A,val b: B) => String
res10: String = herrrrrrp 15 derrrrrrp 16
- methods-not-being-first-class 是一种限制,可能是由 Scala 的 JVM 交互强加的,还是语言设计的决定?
- 为什么我需要自己滚动 eta abstractions,如
merp3
?
merp4
也是一个 eta abstraction,还是偷偷摸摸地相似?
- 为什么我的
etaAbstractor
有效? Scala 是否正在悄悄地用 intCombiner _
替换 intCombiner
?
欢迎提供理论上的计算机科学答案,以及指向 language specification 中任何相关点的指针。谢谢!
它与 etaAbstractor
一起工作的原因是编译器可以推断出需要一个函数(而不是函数调用)。
如果我不得不猜测为什么在无法推断函数类型的地方需要下划线,我认为这是为了改进常见的错误报告class 的错误(在预期调用的地方获取函数)。但同样,这只是一个猜测。
在JVM中,方法不是对象,而first-class函数必须是对象。所以必须将方法装箱到对象中才能将其转换为函数。
免责声明:我不是计算机科学家,但我会尝试猜测:
我刚刚开始使用 Scala,正在修改工作表。例如:
def merp(str: String) : String = s"Merrrrrrrp $str"
val merp2 = (str: String) => s"Merrrrrrrp $str"
val merp3 = (str: String) => merp(str)
val merp4 = merp _
merp("rjkghleghe")
merp4("rjkghleghe")
以及相应的工作表结果:
merp: merp[](val str: String) => String
merp2: String => String = <function1>
merp3: String => String = <function1>
merp4: String => String = <function1>
res0: String = Merrrrrrrp rjkghleghe
res1: String = Merrrrrrrp rjkghleghe
例如,说 val merp5 = merp
会产生错误,因为显然方法不能像函数那样作为值。但我仍然可以将方法作为参数传递。我在以下代码片段中对此进行了演示,改编自 a similar SO question:
def intCombiner(a: Int, b: Int) : String = s"herrrrrrp $a derrrrrrp $b"
def etaAbstractor[A, B](combineFoo: (A, B) ⇒ String, a: A, b: B) = combineFoo(a, b)
etaAbstractor(intCombiner, 15, 16)
工作表结果:
intCombiner: intCombiner[](val a: Int,val b: Int) => String
etaAbstractor: etaAbstractor[A,B](val combineFoo: (A, B) => String,val a: A,val b: B) => String
res10: String = herrrrrrp 15 derrrrrrp 16
- methods-not-being-first-class 是一种限制,可能是由 Scala 的 JVM 交互强加的,还是语言设计的决定?
- 为什么我需要自己滚动 eta abstractions,如
merp3
? merp4
也是一个 eta abstraction,还是偷偷摸摸地相似?- 为什么我的
etaAbstractor
有效? Scala 是否正在悄悄地用intCombiner _
替换intCombiner
?
欢迎提供理论上的计算机科学答案,以及指向 language specification 中任何相关点的指针。谢谢!
它与 etaAbstractor
一起工作的原因是编译器可以推断出需要一个函数(而不是函数调用)。
如果我不得不猜测为什么在无法推断函数类型的地方需要下划线,我认为这是为了改进常见的错误报告class 的错误(在预期调用的地方获取函数)。但同样,这只是一个猜测。
在JVM中,方法不是对象,而first-class函数必须是对象。所以必须将方法装箱到对象中才能将其转换为函数。
免责声明:我不是计算机科学家,但我会尝试猜测: