Показаны сообщения с ярлыком fprog. Показать все сообщения
Показаны сообщения с ярлыком fprog. Показать все сообщения

среда, 23 декабря 2009 г.

Элементы функциональных языков. Резюме.

Дочитал таки статью "Элементы функциональных языков", мысль по прочтению только одна: если бы хаскелисты освоили Common Lisp, то большинство из них забыло бы про Haskell как про страшный сон :)

четверг, 1 октября 2009 г.

Что я думаю о ФП

Наблюдая очередной срач на LOR-е, посвящённый выходу второго номера журнала "Практика функционального программирования" не перестаю удивляться. Дело дошло до обсуждения идиотского примера приготовления яичницы: как лучше описать решение? В императивном или функциональном стиле? Или может ещё надо добавить немного ООП?

Я не знаю... А кто это может знать? Приступая к разработке какого-либо сложного "куска кода" я слишком мало знаю о нём, что бы обоснованно судить какая парадигма лучше всего подходит. А пишу криво и много выкидываю, затем переделываю, снова и снова. И вот, после многократного рефакторинга, после многих дней или недель работы над проблемой, когда я уже знаю очень много и о проблеме и об коде, который написал, у меня может появиться мнение о предпочтительной парадигме, не в результате предварительного анализа, но в результате естественного развития кода.

В начале SICP приводится мнение, что
Программы пишутся, чтобы люди их читали, и лишь иногда - чтобы машины их выполняли
- я думаю, что оно немного устарело. Программы пишутся для того, чтобы люди их редактировали. Если бы программы писались лишь один раз, то, вероятно, стоило бы рассуждать о преимуществах функциональной или императивной парадигмы. Но если вы считаете, что разработка это, прежде всего, процесс экспериментирования и переписывания (рекомендую яркое эссе Пола Грэма на эту тему: "Хакеры и художники"), то проблематика выбора парадигмы отходит на второй план, гораздо важнее другие вещи: насколько легко вы можете внести в программу изменения и увидеть их результат? или насколько легко вы можете диагностировать ошибку?

Common Lisp удивительно хорош не только тем, что сочетает в себе различные парадигмы, что даёт возможность осуществить смену парадигмы для конкретного куска кода без смены языка, но и тем, что значительная часть языка посвящена облегчению процесса программирования (хакерства - в терминологии Пола Грэма), не облегчения кодирования известного алгоритма (хотя и в этом с ним мало кто может соперничать), но прежде всего поддержке процесса поиска решения. И благодаря именно этим возможностям возможен такой мощный инструмент, как SLIME. Пара свежих примеров из собственной практики:
  • Порой хочется пропатчить какую-нибудь библиотеку, что бы изменить поведение какой-либо функции. Просто для проверки, как изменится поведение моего кода. Либо порой может оказаться полезным добавить в библиотечную функцию диагностическое сообщение. При использование многих других языков это довольно проблематично, надо сделать очень много действий и обычно, без крайней необходимости, лучше такого не делать. В Common Lisp при использование SLIME это настолько тривиально, что я пользуюсь этим приёмом постоянно, надо то: установить курсор в месте вызова функции, нажать C-M-. - в результате откроется код нужной функции, с помощью C-x C-q переключить флаг read-only (это даст возможность редактировать буфер, но не сохранить на диск), исправить код и теперь С-M-x перекомпилирует изменённую функцию, всё, можно смотреть как изменилось поведение программы

  • Сайт lisper.ru иногда зависает. Это случается достаточно редко и у меня до сих не было возможности диагностировать ошибку. Но вот вчера сайт снова завис, а я имел немного свободного времени, что бы разобраться. Выяснение точного места в коде, приводящего к этому заняло менее 5 минут: с помощью SLIME подключился к серверу (который находится в другой стране), получил список потоков, выбрал поток "Hunchentoot listener" и выполнил команду slime-thread-debug, что привело к выводу стека вызовов зависшего потока, я увидел необработанное исключение и в течении минуты установил точное место в коде hunchentoot, где оно возникает и не получает должной обработки (надо заметить, это довольно редкая проблема, по крайней мере, я сталкиваюсь с ней только на одном сервере и то, иногда).
Может быть программы на ФП-языках действительно занимают меньшее количество строк кода и их проще понимать (при должной сноровке), чем программы на иных языках, хотя мне совершенно не понятно на чём основано подобное мнение (если проводить сравнение ФП-языков с таким языками как Common Lisp или Python; понятно, что трудно выглядеть проигрышно по сравнение с С). Но какое это имеет значения? Если важна на самом деле не красота/лаконичность законченного решения, а сложности пути, которым оно было достигнуто... ИМХО, сторонники ФП слишком большой упор делают на фукнциональную парадигму, на рассказы о том, насколько хорош язык для кодирования заранее известных алгоритмов (может быть это и так, но мне не очень это интересно), но вопрос применимости языков для реальной разработки остаётся соверешенно открытым. Можно ли пользоваться ФП без боли?

В общем, я хорошего мнение о функциональной парадигме как таковой, но совершенно против языков подобных Haskell.