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.
a new value can be defined with keyword val. eg. val x: Int = 5. Here type is optional as scala can infer it from the assigned value.
def is the keyword you use to define a method, the method name is double , and the input parameter a has the type Int , which is Scala's integer data type. The body of the function is shown on the right side, and in this example it simply doubles the value of the input parameter a : def double(a: Int) = a * 2 -----
Difference between Scala Functions & Methods: Function is a object which can be stored in a variable. But a method always belongs to a class which has a name, signature bytecode etc. Basically, you can say a method is a function which is a member of some object.
The multiple assignments can be possible in Scala in one line by using 'val' keyword with variable name separated by commas and the "=" sign with the value for the variable.
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.
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 cached
lazy val
is lazy and cached (so are memoized def
s)def
is lazy and uncached
def 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With