Что дает ФП мне лично на практике

Aug 26, 2009 23:12

У lionet развернулась дискуссия о рационализации невежества.

По мотивам ее пишу сей составной пост из двух моих комментариев, один из которых был написан в меру давно при подобных же обстоятельствах, второй из которых - в этой дискуссии, и вынесен в отдельный пост по просьбам трудящихся.

1.

Я вот пишу на работе на джаве. Мой опыт использования полученных в результате изучения функциональщины знаний и умений, например, таков:
- Роботоловилка - сложный вычислительный кусок кода; написана почти целиком на функциях высшего порядка (ФВП), но все их уродство скрыто в утилитном классе в паре дюжин нелаконичных, но кричаще-корректных примитивов и комбинаторов. Основная логика выражена через них буквально в нескольких строчках, читающихся как текст на английском языке. С момента написания в этом алгоритме не найдено ни одного бага.
- Писал какую-то штуку для анализа HTML-страничек. Чуть не сдох, пока написал кое-как правильный обходчик DOM в определенном порядке с одновременным вычислением чего-то там хитрого в узлах. Было несколько почти одинаковых кусков кода с обходом и одновременным вычислением, и у всех были какие-нибудь разные баги в обходе: то атрибуты как-то не так обходятся, то текстовые узлы, то еще что. Мне это надоело, и я переписал все это на свёртки: отдельно - обобщенный обходчик как пара ФВП, отдельно - обобщенная свертка. Мигом пропали все до единого баги; код стал тривиален для понимания, и почти что на следующий же день оказалось, что код почти без усилий можно применить в соседней команде, где вместо DOM было что-то другое, но тоже древесное. (Примечание: Сегодня я расширил этот код еще раз под конкретную сегодняшнюю задачу, не трогая фреймворк - не представляю себе, как бы я это сделал, если бы он был написан не так, как сейчас - на основе ФВП - а как-нибудь "по обычному", как я бы его написал, если бы не был знаком с ФП)
- Написал через ФВП кучку утилит для доступа к БД (более конкретно - примитивов и комбинаторов для Spring.JDBC: RowMapper/RowCallback/...); код сокращается местами в 2-3 раза; становится гораздо читаемей; этим хозяйством охотно пользуется вся немаленькая команда.
- Товарищ из "Календаря" долго (несколько недель) мучился с противоречиями в их системе контроля доступа. Я предложил ему воспользоваться вместо неформальных рукомахательств - нотацией Пролога; я ему объяснил эту нотацию и семантику; мы посидели пару часов у доски с фломастером и придумали, вроде бы, хорошую концепцию. Тем же вечером он формализовал бОльшую его часть собственно на настоящем прологе (правда, не довел до запускаемого состояния; все-таки пролог за 1 день в мозги не впихнешь как следует). В течение короткого времени новая система (написанная, как и старая, на Java) была реализована; никаких проблем в ней не обнаружено.

Во всех случаях, как видно, знакомство с миром декларативного и функционального программирования приводило к самым положительным последствиям :)

2.

В контексте http://lionet.livejournal.com/38971.html?thread=675131#t675131
Допустим, Вы программируете на С/C++/Perl/PHP. Что именно Вы сможете применить из ФП в рамках _этих_ инструментов?

- Функции высшего порядка и замыкания (пусть даже эмулированные с помощью указателей на функцию + void *data) и, во всяком случае, саму идею combinator library
- Ленивые вычисления в какой-либо форме
- Будучи знакомым с понятием зависимых типов, гораздо легче понять и эффективно использовать шаблоны С++
- Будучи знакомым с классами типов (typeclasses), я смогу эмулировать их с помощью dictionary-passing style (тем более в С++) и пользоваться приемами, типичными для классов типов.
- Чисто функциональные структуры данных (на С/C++ - с подсчетом ссылок, за отсутствием GC)
- Алгебраические типы - я смогу а) использовать их для моделирования предметной области и б) сэмулировать их с помощью абстракции конструкторов/селекторов/предикатов; разве что без pattern matching.
- Будучи знакомым с prolog-style унификацией, я смогу (пусть и в редких случаях) сэмулировать ее и воспользоваться этим для упрощения какой-нибудь очень сложной условной логики. Я это уже один раз делал, после того как где-то час пытался написать логику красиво обычными if/else и понял, что без ошибок я ее не напишу - и, как обычно и бывает - написал минут за 15, и все сразу же заработало правильно.
- Будучи знакомым с параметрическим полиморфизмом, я буду проектировать полиморфные функции по возможности параметрически полиморфными, что увеличит корректность моих программ и упростит рассуждения о них
- Имея опыт программирования на чистом языке, я буду знать, насколько сильно чистота увеличивает корректность, и буду минимизировать и изолировать в своих программах побочные эффекты, что положительно скажется на корректности
- Будучи знакомым с системами эффектов, я буду иметь возможность рассуждать об эффектах, производимых теми или иными процедурами в моей программе, что также положительно скажется на корректности моей программы и уменьшит количество "сюрпризов" и неявных взаимодействий в ней
- Будучи знакомым с монадами или хотя бы ФВП, я смогу придумать хороший способ организации асинхронных вычислений
- Будучи знакомым с continuations, я смогу при необходимости частично сэмулировать их с помощью getcontext/setcontext и реализовать себе зеленые нити или корутины. И, соответственно, смогу разглядеть задачу, где это действительно будет уместно
- Будучи знакомым с понятием структурной рекурсии и с ее приятными свойствами (гарантированная завершаемость, очень легко рассуждать о структурно-рекурсивных процедурах), я буду по возможности использовать ее вместо общей рекурсии, что положительно скажется на корректности моих каких-нибудь сложных процедур обработки данных
- Будучи знакомым с понятием хвостового вызова и с процедурой его удаления, я смогу не задумываясь и не ошибаясь оптимизировать некоторые рекурсивные процедуры
- ...
Во всех случаях благодаря тому, что я знаком с какой-либо ФПшной концепцией, я могу разглядеть ее полезность в той или иной задаче (в то время как незнакомым с ней придется самим ее изобретать или искать обходные пути), и, будучи знаком со способами реализации этой концепции, сэмулировать ее или воспользоваться ее основными идеями в своей задаче на своем языке.
Previous post Next post
Up