How are methods evaluated in Scala?

Viewed 203

Method types have no value. How do we evaluate a method?

Using SML as an example, I have

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

In the second expression, myFun has a type and a value, we use its type to do type checking and use its value together with its argument to evaluate value for b

But in Scala methods without a value how do we evaluate? I am pretty new to Scala so it may not be very clear.

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

From val b = myFunc(2) to val b = 2 + 5, what happened in between? From where or what object do we know that myFunc(x) is x + 5?

THanks!!

2 Answers

The simple answer is: just because a method is not a value in the sense of "a thing that can be manipulated by you" doesn't mean that it is not a value in the sense of "a thing that can be manipulated by the author of the compiler".

Of course, a method will have an object representing it inside of the compiler. In fact, that object will probably look very similar to the object representing a function inside, say, the MLTon SML compiler or SML/NJ.

In SML, syntax is not a value, but you are not questioning how it is possible to write a function call either, aren't you? After all, in order to call a function in SML, I need to write a function call using function call syntax, so how can I do that when syntax is not a value?

Well, the answer is the same: just because syntax is not a value that the programmer can manipulate, the compiler (or more precisely the parser) obviously does know about syntax.

I can't tell you why the decision was made to have functions be values in Scala but not methods, but I can make a guess. Scala is an object-oriented language. In an object-oriented language, every value is an object, and every object has methods that are bound to that object. So, if methods are objects, they need to have methods, which are objects, which have methods, which are objects, and so on.

There are ways to deal with this, of course, but it makes the language more complex. For a similar reason, classes aren't objects (unlike, say, in Smalltalk, Python, and Ruby). Note that even in highly reflective, introspective, dynamic languages like Ruby, methods are not objects. Classes are, but not methods.

It is possible using reflection to get a proxy object that represents a method, but that object is not the method itself. And you can actually do the same in Scala as well.

And of course it is possible to turn a method into a function value by η-expansion.

I'm assuming that you're compiling to Java Virtual Machine (JVM) bytecode, such as with scalac, which is probably the most common way to use Scala. Disclaimer: I'm not an expert on the JVM, so some parts of this answer might be a bit wrong, but the general idea is right.

Essentially, a method is a set of instructions for the runtime to execute. It exists as part of the compiled code on disk (e.g. a .class file). When the JVM loads the class, it pulls the entire class file into memory, including the methods. When the JVM encounters a method call, it looks up the method and starts executing the instructions in it. If the method returns a result, the JVM makes that result available in the calling code, then does whatever you wanted to do with it there, such as assigning to a variable.

With that knowledge, we can answer some of your questions:

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

This isn't quite how it works, as the JVM doesn't "expand" myFunc in place, but instead looks up myFunc and executes the instructions in it.

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

Not from any object. While myFunc is in memory, it's in an area of memory that you can't access directly (but the JVM can).

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

Not all memory fits into the nice abstractions of types and values.

Related