Я не согласен с ответом WReach. Давайте немного разберем его ответ, чтобы увидеть, откуда возникли разногласия.
Сначала его код:
function allOdd(words) {
var result = true;
for (var i = 0; i < length(words); ++i) {
var len = length(words[i]);
if (!odd(len)) {
result = false;
break;
}
}
return result;
}
и
function allOdd(words) {
return apply(and, map(compose(odd, length), words));
}
Первое, что нужно отметить, это то, что он объединяет:
- Функциональное
- Выражение ориентировано и
- Итератор центрированный
программирование и отсутствие возможности итеративного программирования стиля иметь более явный поток управления, чем типичный функциональный стиль.
Давайте быстро поговорим об этом.
Стиль, ориентированный на выражения, - это тот, в котором вещи, насколько это возможно, оценивают вещам. Хотя функциональные языки славятся своей любовью к выражениям, на самом деле можно иметь функциональный язык без составных выражений. Я собираюсь сделать один, где есть нет выражений, просто заявления.
lengths: map words length
each_odd: map lengths odd
all_odd: reduce each_odd and
Это почти то же самое, что и раньше, за исключением того, что функции связаны только через цепочки операторов и привязок.
Итераторно-ориентированный стиль программирования может быть принят Python. Давайте используем чисто итеративный стиль, ориентированный на итератор:
def all_odd(words):
lengths = (len(word) for word in words)
each_odd = (odd(length) for length in lengths)
return all(each_odd)
Это не функционально, потому что каждое предложение является итеративным процессом, и они связаны друг с другом явной паузой и возобновлением кадров стека. Синтаксис может быть частично основан на функциональном языке, но он применяется к полностью итеративному варианту его реализации.
Конечно, вы можете сжать это:
def all_odd(words):
return all(odd(len(word)) for word in words)
Императив теперь выглядит не так плохо, а? :)
Последний пункт был о более явном контроле. Давайте перепишем оригинальный код, чтобы использовать это:
function allOdd(words) {
for (var i = 0; i < length(words); ++i) {
if (!odd(length(words[i]))) {
return false;
}
}
return true;
}
Используя итераторы, вы можете иметь:
function allOdd(words) {
for (word : words) { if (!odd(length(word))) { return false; } }
return true;
}
Так что же является точкой функционального языка, если разница между:
return all(odd(len(word)) for word in words)
return apply(and, map(compose(odd, length), words))
for (word : words) { if (!odd(length(word))) { return false; } }
return true;
Основной отличительной чертой функционального языка программирования является то, что он устраняет мутацию как часть типичной модели программирования. Люди часто считают, что это означает, что функциональный язык программирования не имеет операторов или использует выражения, но это упрощения. Функциональный язык заменяет явное вычисление объявлением поведения, которое затем выполняет язык.
Ограничение себя этим подмножеством функций позволяет вам иметь больше гарантий поведения ваших программ, и это позволяет вам создавать их более свободно.
Когда у вас есть функциональный язык, создание новых функций обычно так же просто, как составление тесно связанных функций.
all = partial(apply, and)
Это не просто или, возможно, даже невозможно, если вы явно не управляли глобальными зависимостями функции. Лучшая особенность функционального программирования заключается в том, что вы можете последовательно создавать более общие абстракции и полагать, что они могут быть объединены в единое целое.