Scala 中的方法是如何求值的?

How are methods evaluated in Scala?

方法类型没有价值。我们如何评价一个方法?

以SML为例,我有

fun myFunc(x) = x + 5
val b = myFunc(2)

在第二个表达式中,myFun 有一个类型和一个值,我们使用它的类型来进行类型检查,并使用它的值和它的参数来评估 b[=18 的值=]

但是在没有值的 Scala 方法中我们如何求值呢?我是 Scala 的新手,所以可能不是很清楚。

def myFunc(x) = x + 5
val b = myFunc(2)

val b = myFunc(2)val b = 2 + 5,中间发生了什么?我们从哪里或从什么对象知道 myFunc(x)x + 5?

谢谢!!

简单的回答是:仅仅因为方法不是“可以操纵的东西”意义上的值并不意味着它不是“可以由 编译器作者 操纵的事物”意义上的值。

当然,一个方法在编译器内部会有一个对象来表示它。事实上,该对象可能看起来与表示内部函数的对象非常相似,例如 MLTon SML 编译器或 SML/NJ.

在 SML 中,语法不是值,但您也不会质疑如何编写函数调用,不是吗?毕竟,为了在 SML 中调用一个函数,我需要使用函数调用语法编写一个函数调用,那么当语法不是一个值时我该怎么做呢?

嗯,答案是一样的:仅仅因为语法不是 程序员 可以操纵的值,编译器(或更准确地说是解析器)显然 知道语法。

我无法告诉您为什么决定在 Scala 中让函数成为值而不是方法,但我可以猜测一下。 Scala 是一种 object-oriented 语言。在 object-oriented 语言中,每个值都是一个对象,每个对象都有绑定到该对象的方法。所以,如果方法是对象,就需要有方法,有方法,有方法,有方法,有方法,有对象,等等。

当然有办法处理这个问题,但这会使语言变得更加复杂。出于类似的原因,类 不是对象(与 Smalltalk 中的 Python 和 Ruby 不同)。请注意,即使在像 Ruby 这样高度反思、内省、动态的语言中,方法也不是对象。 类 是,但不是方法。

有可能使用反射得到一个代理对象,代表一个方法,但那个对象不是方法本身。实际上,您也可以在 Scala 中执行相同的操作。

当然也可以通过η展开将方法变成函数值

我假设您要编译成 Java 虚拟机 (JVM) 字节码,例如 scalac,这可能是使用 Scala 的最常见方式。免责声明:我不是JVM专家,所以这个答案的某些部分可能有点错误,但总体思路是正确的。

从本质上讲,方法是运行时要执行的一组指令。它作为编译代码的一部分存在于磁盘上(例如 .class 文件)。当 JVM 加载 class 时,它会将整个 class 文件拉入内存,包括方法。当 JVM 遇到方法调用时,它会查找该方法并开始执行其中的指令。如果方法 returns 一个结果,JVM 使该结果在调用代码中可用,然后在那里做任何你想用它做的事情,比如分配给一个变量。

有了这些知识,我们可以回答您的一些问题:

From val b = myFunc(2) to val b = 2 + 5, what happened in between?

这不是它的工作原理,因为 JVM 不会就地“扩展”myFunc,而是查找 myFunc 并执行其中的指令。

From where or what object do we know that myFunc(x) is x + 5?

不是来自任何对象。虽然 myFunc 在内存中,但它位于您无法直接访问的内存区域(但 JVM 可以)。

why can't it be a value since it is a chunk of memory?

并非所有内存都适合类型和值的漂亮抽象。