После катастрофы шаттла Коламбия в 2003-м мне попалась на глаза статейка, в которой одной из причин называлось широкое использование Microsoft PowerPoint в NASA. Т.е. виноват, конечно, не сам PowerPoint, а использование презентаций в качестве основной формы докладов подразделений и руководству NASA. Презентации, якобы, не позволяли углубляться в детали, а дают только поверхностную картинку. Т.е. подчиненные подсовывали своему начальству красочные презентации, которые начальство хотело видеть. Что и привело с системным проблемам в обеспечении безопасности полетов шаттлов.
Версия, конечно, бредовая. Но негативная роль презентаций, показывающих только “светлую” сторону, определенно есть. Взять, например, презентацию Дона Сайма “Why is Microsoft investing in Functional Programming?”, а в ней картинку на странице 38:
Действительно ли показанный желтым фрагмент на F# является эквивалентом трех страниц на C#?
Как по мне – так нет. Они не эквиваленты ни по выполняемым операциям, ни по объему комментариев в коде, ни по подробности обработки ошибок.
Зато как убедительно преимущество F# выглядит в презентации! ;)
Еще один пример, на этот раз из обсуждавшейся уже здесь статьи “Элементы функциональных языков”. Фрагмент кода из раздела “10. Сопоставление с образцом”, демонстрирующий работу с POP3 сервером:
sendCommand (POP3C conn _) (RETR msg) = bsPutCrLf conn (BS.pack ("RETR " ++ show msg)) >> responseML conn sendCommand (POP3C conn _) (TOP msg n) = bsPutCrLf conn (BS.pack ("TOP " ++ show msg ++ " " ++ show n)) >> responseML conn sendCommand (POP3C conn _) (AUTH LOGIN user pass) = do bsPutCrLf conn (BS.pack "AUTH LOGIN") bsGetLine conn bsPutCrLf conn (BS.pack userB64) bsGetLine conn bsPutCrLf conn (BS.pack passB64) response conn where (userB64, passB64) = A.login user pass |
Красиво? А вот пример работы с POP3 сервером из библиотеки POCO:
void POP3ClientSession::login(const std::string& username, const std::string& password) { std::string response; _socket.receiveMessage(response); if (!isPositive(response)) throw SMTPException("The POP3 service is unavailable", response); sendCommand("USER", username, response); if (!isPositive(response)) throw POP3Exception("Login rejected for user", response); sendCommand("PASS", password, response); if (!isPositive(response)) throw POP3Exception("Password rejected for user", response); } |
Ведь тоже красиво, не так ли? Просто, лаконично, функционально. Лепота.
Одна проблема с кодом в POCO – нихрена тайм-ауты он не считает. Поэтому, если по какой-то причине соединение с POP3 сервером “залипнет” (т.е. из него ничего не будет читаться, но и сигнала о потере не будет), то приложение на вызове POP3ClientSession::login() уснет навсегда.
А если добавить в приведенные выше фрагменты более суровую (т.е. требующуюся на практике) обработку ошибок и тайм-аутов, куда исчезнет эта красота?
Вот о том и речь. Красивые презентации, которые убедительно демонстрируют преимущества одного подхода над другим – это все хорошо. Плохо только, что детали в таких презентациях не видны. Почти как в той статье про причины падения Коламбии.
А если добавить ... обработку ошибок и тайм-аутов
ОтветитьУдалитьИли, как недавно бодался - полусокет в FIN_WAIT2 перешел... и там и остается. И ...ь, пишешь в него - молчит без эксепшна, как будто ушло.
А когда пишешь на ФЯ - такого не бывает. Это у нас, императивщиков то с таймаутами что-то не так, то сокет "залипftn" аки USRobotics.
На ФЯ - все чистенько, все работает...
Имхо, этим страдают все продавцы "серебрянных пуль". ФП же просто сейчас самая серебрянная из всех серебрянных. Поэтому для нее примеры не пришлось долго искать :)
ОтветитьУдалитьЕвангелисты конечно мать родную продадут :) но это не отменяет того что в целом код на функциональщине получается и короче и выразительней.
ОтветитьУдалить>в целом код на функциональщине получается и короче и выразительней.
ОтветитьУдалитьНу, zip-ованный текст в 3-4 раза компактнее обычного, только вот без специальных инструментов не читается :)
В существующей функциональщине степень краткости, имхо, перешла грань разумного. Синтаксис OCaml-а и Haskell-я для большинства нынешних мейнстримщиков хуже китайских иероглифов. Идеи ФП (лямбды, иммутабельность и паттерн-матчинг в первую очередь) проникают и продолжат проникать в мейнстрим (через Java, C#, C++, в меньшей степени через Scala и F#). Что хорошо.
Но хардкорный ФП вроде:
f a b C d E = n d \x :- d :/ g k ^ m >>=%^% W
лучше держать от обычных людей подальше :)
zip-ованный текст длиннее чем программа на J или K :)
ОтветитьУдалитьТак что если гнаться только за краткостью это не к ФП - а к APL based. И до грани разумного тем же OCaml и хаскелю очень далеко :)
Ну и хардкорный C++ по закорючкам и криптостойкости может и фору дать ФП :)
>И до грани разумного тем же OCaml и хаскелю очень далеко :)
ОтветитьУдалитьКак в анекдоте -- "да-а-а, Тал-л-л-ин теперь уже дал-л-лек-о-о" :)
>Ну и хардкорный C++ по закорючкам и криптостойкости может и фору дать ФП :)
Это точно. Была бы ему адекватная замена... А то сейчас D, мне кажется, по количеству закорючек C++ превзойдет. Что там в последних релизах добавилось? auto и auto ref-функции, вроде бы :) Столько всего уже нужно в D знать, OCaml по сравнению с ним выглядит каким-то оборванцем :)
Да D все матереет и матереет, похоже скоро (не пройдет и пяти лет) хаскель и окамл будут его подмножествами :)
ОтветитьУдалить