3
votes

Since and I quote from Martin Odersky:

  • The def form is “by-name”, its right hand side is evaluated on each use.
  • The right-hand side of a val definition is evaluated at the point of the definition itself.

In this case:

  • def loop: Boolean = loop
  • val x = loop // Leads to an infinite loop

In this case:

  • val y: Boolean = y // Evaluated to false

I'm a little confused why:

  • val x = loop // doesn't get evaluated to false?
1
Because in order to evaluate the value of loop you need first to evaluate the value of loop. It's a recursive call without escape condition - SimY4
The emphasis of the question is strange. It's obvious that val x = loop should just hang forever. What's not so obvious is why val y: Boolean = y does anything at all. - Andrey Tyukin
Thank you Andrey for rephrasing my question. I believe that the emphasis of the question is strange as I didn't know the underlying procedures for both def and val. - Muhammad Ezzat

1 Answers

4
votes

If you use

val y: Boolean = y

in statement position inside method body, it doesn't evaluate to anything at all, because it gives a compile time error:

error: forward reference extends over definition of value y

However, if you use it as a member variable, it compiles to a separate private variable initialized with _, a getter def, and a separate initializer:

private[this] val y: Boolean = _;
<stable> <accessor> def y(): Boolean = XeqX.this.y;

[...]

def <init>(): WhateverYourClassIsCalled.type = {
  XeqX.super.<init>();
  XeqX.this.y = XeqX.this.y();
  ()
}

Since _ on right hand side for booleans evaluates to default value false, by the time you access it in initializer, the member y is already set to false.


In contrast to that

def loop: Boolean = loop

never terminates once it's called. Therefore

val x = loop

tries to evaluate its right hand side immediately, and then hangs forever.


Here is another answer for a similar problem (again, difference between def and val).