Под капотом существуют другие различия между функциями и методами. Как правило, простой метод генерирует меньше накладных расходов, чем функция (которая технически является объектом с методом apply
).
Однако, если вы пытаетесь, чтобы не заботиться о тех различиях, и думать о def
, val
и var
как полей с различной семантикой, то это просто, что def
оценивает каждый раз, когда она вызывается, в то время как val
оценивает только один раз.
Таким образом, a val isEven = isDivisibleBy(2)
должен позвонить по телефону isDivisibleBy(2)
во время его определения и присвоить результат isDivisibleBy(2)
. Например. он заменяет k
в
def isDivisibleBy(k: Int): Int => Boolean = i => i % k == 0
с 2
и присваивает результат конечного выражения (в данном случае существует только одно выражение):
val isEven: Int => Boolean = i => i % 2 == 0
def isEven
с другой стороны, делает никакой такой оценки и приводит к вызову isDivisibleBy (2) каждый раз.
Это означает, что позже, при выполнении кода, isEven(11)
генерирует в случае val
11 % 2 == 0
и в случае def
, вы будете иметь
isDivisibleBy(2)(11)
и только после того, как оценивая isDivisibleBy
, вы получите результат.
Вы можете добавить некоторые отладки кода isDivisibleBy
, чтобы увидеть разницу:
def isDivisibleBy(k: Int): Int => Boolean = {
println("evaluating isDivisibleBy")
i => i % k == 0
}
Просто думать об этом в эквивалентной Java (функции против методов делает хорошую работу, что Scala), и как она вписывается в время выполнения. Это хорошая причина для одного подхода к другому. Также обратите внимание, что область «def» важна, поскольку она не везде везде (это всего лишь «метод» - подробности реализации в сторону - на уровне класса). –