Вот вполне себе функциональный код на Java:
String reverseString(String str) {
if (str.length() <= 1) {
return str;
} else {
return
str.charAt(str.length() - 1) +
reverseString(str.substring(1,
str.length() - 1)) +
str.charAt(0);
}
}
Побочных эффектов нету, соблюдается referential transparency.
Проблемы начинаются, когда код становится чуть сложнее, чем просто инвертирование строки. Попробуем написать функцию, которая инвертирует строки текста:
String reverseText(String text) {
String[] lines = text.split("\n");
String[] invertedLines = reverseLines(lines,
0, new String[0]);
return Joiner.on("\n").join(invertedLines);
}
String[] reverseLines(String[] lines, int i, String[] invertedLines) {
if (lines.length - i == 0) {
return invertedLines;
} else {
return reverseLines(lines, i + 1,
ObjectArrays.concat(invertedLines, reverseString(lines[i])));
}
}
Справились, но пришлось добавить вспомогательный метод reverseLines. Естественным образом возникает мысль, что неплохо было бы его спрятать внутрь reverseText. И тогда можно не передавать lines в метод reverseLines, потому что она и так будет видна через замыкание. Таким образом, в функциональном языке мы должны уметь определять функции внутри функций.
Теперь надо написать функцию, которая не просто инвертирует строки текста, а, скажем инвертирует и ещё переводит их в верхний регистр. Очевидно, что функция будет отличаться от предыдущей одной лишь заменой reverseString на reverseStringAndToUpperCase. А дублировать код плохо. Тогда возникает мысль, а можно ли как-нибудь абстрагировать функцию reverseString от инвертирования? Назовём её transformText, а функцию reverseString будем передавать как аргумент. Вот и возникло желание иметь функции как объекты первого класса.
Далее, наверное не сильно хочется писать функцию reverseStringAndToUpperCase? Ведь у нас уже есть reverseString и toUpperCase. Неплохо было бы уметь писать что-нибудь вроде reverseString.andThen(toUpperCase). Т.е. ещё возникает необходимость композиции функций в нашем языке.
Таким образом, писать без побочных эффектов - это трудная задача. А функциональные языки предоставляют инструменты, с помощью которых эту задачу можно значительно упростить.
Хорошая статья.
ОтветитьУдалитьЯ считаю, это правильный подход - объяснять функциональную парадигму, используя простые конструкции из императивных языков типа Джавы. Я пару лет назад тоже писал статью в подобном духе: http://habrahabr.ru/post/122919/
-------
https://twitter.com/eliah_lakhin
Да, помню твою статью. Читал 2 года назад.
Удалить