Что в функциональном программировании имеет значение?
Функциональное программирование в принципе декларативно . Вы говорите, каков ваш результат, а не как его вычислить.
Давайте посмотрим на действительно функциональную реализацию вашего фрагмента. В Хаскеле это было бы:
predsum pred numbers = sum (filter pred numbers)
Понятно, каков результат? Именно такова сумма чисел, соответствующих предикату. Как это вычисляется? Мне все равно, спросите компилятор.
Можно сказать, что используя sum
иfilter
это трюк, и это не считается. Позвольте реализовать это без этих помощников (хотя лучшим способом было бы реализовать их в первую очередь).
Решение «Функциональное программирование 101», которое не использует sum
, с рекурсией:
sum pred list =
case list of
[] -> 0
h:t -> if pred h then h + sum pred t
else sum pred t
Все еще довольно ясно, каков результат с точки зрения одного вызова функции. Это либо 0
, либо recursive call + h or 0
, в зависимости от pred h
. Все еще довольно просто, даже если конечный результат не сразу очевиден (хотя с небольшой практикой это действительно выглядит как for
цикл).
Сравните это с вашей версией:
public int Sum(Func<int,bool> predicate, IEnumerable<int> numbers){
int result = 0;
foreach(var item in numbers)
if (predicate(item)) result += item;
return result;
}
Что в итоге? О, я вижу: одно return
заявление, никаких сюрпризов здесь return result
.
А что есть result
? int result = 0
? Не кажется правильным. Вы делаете что-то позже с этим 0
. Хорошо, вы добавляете item
s к нему. И так далее.
Конечно, для большинства программистов это довольно очевидно, что происходит в такой простой функции, как эта, но добавьте несколько дополнительных return
утверждений или около того, и это вдруг станет сложнее отследить. Весь код посвящен тому , как и что читателю остается понять - это явно очень императивный стиль. .
Итак, переменные и циклы не так?
Нет.
Есть много вещей, которые они гораздо легче объяснить, и много алгоритмов, которые требуют изменяемого состояния, чтобы быть быстрым. Но переменные по своей сути обязательны, объясняя, как вместо того, что , и давая небольшой прогноз того, что их значение может быть несколько строк спустя или после нескольких итераций цикла. Циклы обычно требуют состояния, чтобы иметь смысл, и поэтому они также являются обязательными.
Переменные и циклы просто не являются функциональным программированием.
Резюме
Современное функциональное программирование - это больше стиль и полезный способ мышления, чем парадигма. Сильное предпочтение чистых функций заключается в этом мышлении, но на самом деле это лишь малая часть.
Большинство распространенных языков позволяют использовать некоторые функциональные конструкции. Например, в Python вы можете выбрать между:
result = 0
for num in numbers:
if pred(result):
result += num
return result
или
return sum(filter(pred, numbers))
или
return sum(n for n in numbers if pred(n))
Эти функциональные выражения прекрасно подходят для подобных задач и просто делают код короче (а короче - хорошо ). Не стоит бездумно заменять им императивный код, но когда они подходят, они почти всегда являются лучшим выбором.
item
переменная мутирует в цикле.