Reputation: 195
loop is defined as below:
def loop : Boolean = loop
When x is defined as: def x = loop
then "x: Boolean" is shown in console.
and
When x is defined as: val x = loop
then it goes to infinite loop
I know def is using call by-name and val is using call by-value. Even though this point about loop defined above is not much clear.
Upvotes: 5
Views: 1395
Reputation: 44918
The call-by-name or call-by-value distinction seems less useful in this case, because neither your x
, nor your loop
take any arguments.
But there are two other ways in which val
and def
differ.
First distinction is: eager vs. lazy.
val
is evaluated eagerly, as soon as the val
is defined.def
is evaluated lazily, as soon as the
def
is accessed.For example:
def x = { println("x is evaluated"); 42 }
val y = { println("y is evaluated"); 42 }
x
Will print:
y is evaluated
x is evaluated
because y
is evaluated immediately, whereas x
is evaluated only when we call it.
The other difference is whether the result of the computation is cached or not:
val
is evaluated once, and then cacheddef
is evaluated every time we call the functionThis is why
def dice = { new scala.util.Random().nextInt(6) + 1 }
val once = { new scala.util.Random().nextInt(6) + 1 }
println(dice + " <-> " + once)
println(dice + " <-> " + once)
println(dice + " <-> " + once)
println(dice + " <-> " + once)
will output:
5 <-> 6
4 <-> 6
6 <-> 6
5 <-> 6
that is, dice
is a more or less useful random number generator that generates values 1-6
, whereas once
is a rather useless random value that is fixed once it's created.
Now, you can think of a 2x2-table with eager-vs-lazy in one dimension, and cached-vs-not-cached on the other:
val
is eager and cachedlazy val
is lazy and cached (so are memoized def
s)def
is lazy and uncacheddef main
is a def
, it always gets called anyway, so in a sense it's both kind-of eager and uncached.In your code, loop
is essentially a tail-recursive version of the non-terminating
def loop: Boolean = { while (true) {}; true }
but since loop
is a def
, and therefore lazy, the right hand side is not evaluated when you define it.
If you now define
def x = loop
nothing is happening still, because x
is also lazy, so the right hand side is again not evaluated.
But if you define
val x = loop
then x
is a val
, thus its right hand side is evaluated eagerly. On the right hand side of the definition, there is an invocation of loop
. Now loop
is accessed, and since it is a def
, it now evaluates its body, and goes into an infinite loop.
Upvotes: 9
Reputation: 14073
def
doesn't evaluate the right-hand side of the assignment. Just like
def f(x : Int) = x + 2
doesn't (in this case logically can't) evaluate f
of anything, just defines what the function f
, means, neither def loop : Boolean = loop
nor def x = loop
evaluate anything. You are just defining a function to be executed at some other point.
But val
s do require the right-hand side of the assignment to be evaluated. So val x = loop
tries to execute the expression on the right-hand side. Trying to evaluate loop
never terminates, though, since loop
is an infinite loop.
Upvotes: 10