Why are Scala class methods not first-class citizens?

怎甘沉沦 提交于 2019-12-06 04:49:39

问题


I've just started Scala and am tinkering in worksheets. For example:

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")

And the corresponding worksheet results:

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

Saying, for example, val merp5 = merp produces an error, because apparently methods cannot be values the way functions can. But I can still pass methods as arguments. I demonstrate this in the following code snippet, adapted from 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)

worksheet result:

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

  1. Is methods-not-being-first-class a limitation, perhaps imposed by Scala's JVM interaction, or is it a decision in the language's design?
  2. Why do I need to roll my own eta abstractions, as in merp3?
  3. Is merp4 also an eta abstraction, or is it something sneakily similar?
  4. Why does my etaAbstractor work? Is Scala quietly replacing intCombiner with intCombiner _?

Theoretical, computer sciencey answers are welcome, as are pointers to any relevant points in the language specification. Thanks!


回答1:


Disclaimer: I'm not a computer scientist, but I will try to guess:

  1. Method is a part of an object and doesn't exist outside of it. You can't pass method alone. Closure is another (equivalent?) way of encapsulating state, by converting an object method to a standalone function (which is by the way just another object with apply() method in Scala) you are creating a closure. This process is known as eta-expansion. §3.3.1, §6.26.5

  2. You don't have to. You can also write val merp3 : (String => String) = merp. §6.26.5

  3. Yes, merp4 is eta-expansion too. §6.7

  4. §6.26.2




回答2:


The reason it works with etaAbstractor is that the compiler can infer that a function (not a function invocation) is required.

If I had to guess why the underscore is required where a function type cannot be inferred, I'd think that it's to improve error reporting of a common class of errors (getting functions where invocations are intended). But again, that's just a guess.

In the JVM, a method is not an object, whereas a first-class function must be one. So the method must be boxed into an object to convert it to a function.



来源:https://stackoverflow.com/questions/30495571/why-are-scala-class-methods-not-first-class-citizens

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!