Функции против методов в Scala - PullRequest
44 голосов
/ 30 января 2011

Я смотрю Рунар Бьярнасон представляет функциональное программирование для начинающих , и в 14:45 он определяет метод:

def isDivisibleBy(k: Int): Int => Boolean = i => i % k == 0

и функция:

val isEven = isDivisibleBy(2)

Каковы плюсы и минусы определения isEven как функции, а не метода?

Я прочитал Функции Scala и Методы , а также Разница между методом и функцией в Scala , и я понимаю семантические различия, но мне интересно, есть ли более глубокая причина случай, когда функция может или не может быть предпочтительнее использования метода:

def isEven = isDivisibleBy(2)

Ответы [ 4 ]

60 голосов
/ 30 января 2011

Под капотом есть другие различия между функциями и методами.Обычно простой метод генерирует меньше накладных расходов, чем функция (технически это объект с методом apply).

Однако, если вы попытаетесь не заботиться об этих различиях и подумаете о def, val и var как поля с различной семантикой, тогда просто def оценивает каждый раз, когда вызывается, в то время как val оценивает только один раз.* должен вызвать isDivisibleBy(2) во время его определения и присвоить результат isDivisibleBy(2).Например, он заменяет k в

def isDivisibleBy(k: Int): Int => Boolean = i => i % k == 0

на 2 и присваивает результат конечного выражения (в данном случае есть только одно выражение):

val isEven: Int => Boolean = i => i % 2 == 0

*С другой стороны, 1024 * не выполняет такую ​​оценку и каждый раз приводит к вызову 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
}
18 голосов
/ 30 января 2011

Я хотел бы обратиться к другому вопросу здесь.Это определяет isEven как метод:

def isEven = isDivisibleBy(2)

И это также определяет isEven как метод:

val isEven = isDivisibleBy(2)

В обоих случаях isEven является методом,при вызове вернуть функцию.

В первом случае isDivisible(2) вызывается каждый раз, когда вызывается isEven.Например, это вызывает isDivisible(2) три раза:

def isEven = isDivisibleBy(2)
List(1,2,3).filter(isEven)

Во втором случае isDivisible(2) вызывается один раз (во время построения или при выполнении этой строки в определении), и это значениеизвлекается каждый раз, когда вызывается isEven.Следующий пример вызывает isDivisible(2) только один раз:

val isEven = isDivisibleBy(2)
List(1,2,3).filter(isEven)
6 голосов
/ 30 января 2011

Я думаю, что основной плюс определения функции isEven как val - показать аудитории, что функция может быть определена таким образом. Тогда ясно, что функция - это просто объект, как и все в scala. Но в мире не демонстрирующего программирования нет необходимости писать функции как val s.

3 голосов
/ 30 января 2011

Метод def isDivisibleBy(k: Int): Int => Boolean возвращает функцию, которая принимает Int (i) в качестве параметра и возвращает логическое значение (i % k == 0).

val isEven = isDivisibleBy(2), с другой стороны, представляет собой поле, в котороефункция, возвращаемая isDivisibleBy(2), сохраняется.Если вы используете def вместо val, то метод isDivisibleBy будет вызываться каждый раз, когда вызывается метод isEven, но теперь он вызывается только один раз, а результат сохраняется в поле.

Вы можете достичьтот же результат, написав def isEven(i: Int): Boolean = i % 2 == 0

Я думаю, что смысл примера в том, что вы можете иметь функции, которые возвращают другие функции, и вы можете сохранять функции как объекты, а затем вызывать их, как если бы они были традиционноопределенные методы.Вышеприведенный код также очень похож на curry , так что это может также быть одной вещью, продемонстрированной примером (хотя он не использует синтаксис Scala для каррирования ).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...