Reputation: 2588
Trying to figure out the significance of this section from Programming in Scala, 2nd edition.
A function literal is compiled into a class that when instantiated at run- time is a function value. Thus the distinction between function literals and values is that function literals exist in the source code, whereas function val- ues exist as objects at runtime. The distinction is much like that between classes (source code) and objects (runtime).
I don't really get what they're trying to say here. That function values don't exist in the source code and function literals don't exist at runtime?
// literal
val addOne = (x: Int) => x + 1
// value
def add1(x: Int): Int = x + 1
I can pass either to another function:
def doThing(thing: Int => Int) = thing(5)
doThing(addOne) // 6
doThing(add1) // 6
It also appears that function literals are placed into a class that inherits from FunctionN
(where N is the arity of the function). What distinction are they trying to make here?
Upvotes: 6
Views: 1184
Reputation: 369420
There's nothing special about functions in that paragraph. It applies exactly the same to other kinds of literals, e.g. integers.
0x34
followed by the character with the ASCII value 0x32
and surrounded by whitespace, parentheses, comma, semicolon, or some other kind of delimiter, is an integer literal.Int
class. (Actually, that's not quite true: on the JVM implementation of Scala, it will be compiled into a JVM primitive int
, and on the ECMAScript implementation of Scala, it will be compiled into an ECMAScript Number
, and the compiler will generate additional code to "fake" it being an instance of the scala.Int
class.)42
.Functions are no different here. The specific sequence of characters that make up a literal (whether that be a function literal, integer literal, string literal, character literal, symbol literal, tuple literal, boolean literal, or the literal value null
) exist only in the source code. The values those literals represent exist only at runtime. The compile time representation of those literals is as an instance of some class.
Upvotes: 0
Reputation: 149518
I don't really get what they're trying to say here.
Your example of a function literal and value aren't accurate. The book is not comparing methods to functions, it's creating a distinction between two different "modes" of a function. The hint is in the first sentence:
A function literal is compiled into a class that when instantiated at run-time is a function value.
When at compile time you type:
val addOne = (x: Int) => x + 1
This is what the book refers to as a "function literal" (or Anonymous Function). The same way you have a string literal by typing:
val s = "Hello, World"
addOne
to the compiler is a Function1[Int, Int]
, meaning takes an Int
and returns an Int
result. The function literal syntax ((x: Int) => x + 1
) is syntactic sugar over FunctionN
, where N
is determined by the arity of the function.
At run-time, the compiler takes this "function literal" and "puts life into it" by instantiating an object of type Function1[Int, Int]
, thus creating a function value which you can invoke, pass around, etc.
What distinction are they trying to make here?
The book is basically trying to create a distinction between the compile time and runtime representation of a function, so when they say "function literal" you'll understand they're talking about the former, and when they say "function value" the latter.
Upvotes: 4
Reputation: 5424
Scala code compiles into jvm bytecode which does not have functions but has classes. So your code val addOne = (x: Int) => x + 1
is syntactic sugar for (I'm not precise here, only high concepts):
final class anonFun extends scala.runtime.AbstractFunction1 {
final def apply(x: Int) = x + 1
}
val addOne = new anonFun();
Actually compiled files are much more complex, you can compile your scala file with scalac -print
and see desugared scala code. Here is my compile output of small object:
object Main {
val addOne = (x: Int) => x + 1
}
(scalac version 2.11.7)
package <empty> {
object Main extends Object {
private[this] val addOne: Function1 = _;
<stable> <accessor> def addOne(): Function1 = Main.this.addOne;
def <init>(): Main.type = {
Main.super.<init>();
Main.this.addOne = {
(new <$anon: Function1>(): Function1)
};
()
}
};
@SerialVersionUID(value = 0) final <synthetic> class anonfun$1 extends scala.runtime.AbstractFunction1$mcII$sp with Serializable {
final def apply(x: Int): Int = anonfun$1.this.apply$mcII$sp(x);
<specialized> def apply$mcII$sp(x: Int): Int = x.+(1);
final <bridge> <artifact> def apply(v1: Object): Object = scala.Int.box(anonfun$1.this.apply(scala.Int.unbox(v1)));
def <init>(): <$anon: Function1> = {
anonfun$1.super.<init>();
()
}
}
}
At the contrast look at compiling
object Main {
def addOne(i: Int) = i + 1
}
(scalac version 2.11.7)
package <empty> {
object Main extends Object {
def addOne(i: Int): Int = i.+(1);
def <init>(): Main.type = {
Main.super.<init>();
()
}
}
}
You can see that def addOne
becomes just an instance method of an object, but val addOne
is itself an object.
Upvotes: 3