вторник, 15 октября 2013 г.

Мысли об ФП

ФП - это программирование без побочных эффектов. На этом определение ФП заканчивается. А лямбды, функции как объекты первого класса, композиция и прочие функциональные штуки - это всё второстепенно.

Вот вполне себе функциональный код на 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). Т.е. ещё возникает необходимость композиции функций в нашем языке.

Таким образом, писать без побочных эффектов - это трудная задача. А функциональные языки предоставляют инструменты, с помощью которых эту задачу можно значительно упростить.

понедельник, 14 октября 2013 г.

X vs Y

Windows vs Linux vs OS X
Git vs Mercurial vs SVN
Facebook vs Twitter vs Google+
Skype vs Gtalk
Microsoft vs Google vs Oracle
Eclipse vs IDEA vs Netbeans
Github vs Bitbucket vs Google Code
XML vs JSON vs YAML
Vim vs Emacs vs Sublime Text
Android vs iOS
Tabs vs Spaces
C# vs Java
CLR vs JVM
Ruby vs Python vs PHP vs JavaScript
Scala vs Clojure vs Erlang
Static Typing vs Dynamic Typing
Any X vs Any Y

Может, уже пора просто делать свою работу?