The difference between val and def becomes apparent when the
right hand side does not terminate.
def loop: Boolean = loop
def x = loop
is OK, but a definition
val x = loop
will lead to an infinite loop.
Function parameters can be passed by value or be passed by name.
The same distinction applies to definitions.
The def form is “by-name”, its right hand side is evaluated on each use.
There is also a val form, which is “by-value”.
val x = 2
val y = square(x)
The right-hand side of a val definition is evaluated at the point of
the definition itself.
Afterwards, the name refers to the value.
For instance, y above refers to 4, not square(2).