Under the hood, there are other differences between functions and methods. Generally, a plain method generated less overhead than a function (which technically is an object with an apply
method).
However, if you try not to care about those differences and think of def
, val
and var
as fields with different semantics, then it’s simply that def
evaluates every time it gets called while val
evaluates only once.
So, a val isEven = isDivisibleBy(2)
should call isDivisibleBy(2)
during its definition and assign the result of isDivisibleBy(2)
. E.g. it replaces the k
in
def isDivisibleBy(k: Int): Int => Boolean = i => i % k == 0
with 2
and assigns the result of the final expression (in this case there is only one expression):
val isEven: Int => Boolean = i => i % 2 == 0
def isEven
on the other hand does no such evaluation and results in a call to isDivisibleBy(2) every time.
That means, later, when you execute the code, isEven(11)
generates in case of a val
11 % 2 == 0
and in case of a def
, you’ll have
isDivisibleBy(2)(11)
and only after evaluating isDivisibleBy
you’ll get the result.
You can add some debug code to isDivisibleBy
to see the difference:
def isDivisibleBy(k: Int): Int => Boolean = {
println("evaluating isDivisibleBy")
i => i % k == 0
}