Хорошо ли справляются функциональные языки со сложностью? - PullRequest
6 голосов
/ 02 февраля 2010

Мне любопытно, как функциональные языки сравниваются (в целом) с более "традиционными" языками, такими как C # и Java для больших программ.Становится ли трудным следовать за ходом программы быстрее, чем при использовании нефункционального языка?Есть ли другие вопросы или вещи, которые следует учитывать при написании большого программного проекта с использованием функционального языка?

Спасибо!

Ответы [ 6 ]

14 голосов
/ 02 февраля 2010

Функциональное программирование стремится уменьшить сложность больших систем, изолируя каждую операцию от других. Когда вы программируете без побочных эффектов, вы знаете, что вы можете посмотреть на каждую функцию индивидуально - да, понимание того, что одна функция может также включать в себя понимание других функций, но, по крайней мере, вы знаете, что это не повлияет на какой-то другой фрагмент состояния системы в другом месте.

Конечно, это предполагает абсолютно чистое функциональное программирование - что, конечно, не всегда так. Вы также можете использовать более традиционные языки функционально, избегая, по возможности, побочных эффектов. Но этот принцип важен: избегание побочных эффектов приводит к созданию более понятного, понятного и тестируемого кода.

9 голосов
/ 03 февраля 2010

Становится ли трудным следовать за ходом программы быстрее, чем если бы> нефункциональный язык использовался?

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

Есть ли другие вопросы или моменты, которые следует учитывать при написании большого программного проекта с использованием функционального языка?

критической вещью является хорошая модульная система.Вот некоторые комментарии.

  • Самая мощная из известных мне модульных систем из модульной системы PLT Scheme , разработанной Мэтью Флэттом и Матиасом Феллайзеном.К сожалению, в этой очень мощной системе отсутствуют статические типы, которые я очень помогаю программированию.

  • Следующая наиболее мощная система - модульная система Standard ML.К сожалению, Standard ML, хотя и очень выразительный, также допускает множество сомнительных конструкций, поэтому любителю легко устроить настоящий беспорядок.Кроме того, многим программистам трудно эффективно использовать модули Standard ML.

    Система модулей Objective Caml очень похожа, но есть некоторые различия, которые, как правило, смягчают худшие излишки Standard ML.Языки на самом деле очень похожи, но стили и идиомы Objective Caml значительно снижают вероятность того, что новички будут писать безумные программы.

  • Наименее мощная / выразительная модульная система для функционального языкаявляется модульной системой HaskellЭта система имеет серьезный дефект: нет явных интерфейсов , поэтому большая часть когнитивного преимущества наличия модулей потеряна.Другим печальным результатом является то, что, хотя система модулей Haskell предоставляет пользователям иерархическое пространство имен, использование этого пространства имен (import qualified, в случае, если вы инсайдер) часто не рекомендуется, и многие программисты на Haskell пишут код, как будто все водно большое, плоское пространство имен.Эта практика сводится к отказу от еще одного большого преимущества модулей.

Если бы мне пришлось писать большую систему на функциональном языке и быть уверенным, что другие люди поняли это, я 'Я бы, вероятно, выбрал Standard ML, и я бы установил очень строгие правила программирования для использования системы модулей.(Например, явные подписи везде, непрозрачные надписи с :> и отсутствие использования open где-либо, когда-либо.) Для меня простота основного языка стандарта ML (по сравнению с OCaml) и более функциональная природа СтандартаML Basis Library (по сравнению с OCaml) более ценна, чем превосходящие аспекты модульной системы OCaml.

Я работал только над одной действительно большой программой на Haskell, и пока нашел (и продолжаю находить)работать в Haskell очень приятно, я действительно упустил отсутствие явных подписей.

Хорошо ли справляются функциональные языки со сложностью?

Некоторые делают.Я обнаружил, что модули ML и типы модулей (как Standard ML, так и Objective Caml) представляют собой бесценные инструменты для управления сложностью, понимания сложности и размещения недоступных межсетевых экранов между различными частями больших программ.У меня был менее хороший опыт работы с Haskell


Последнее замечание: это не совсем новые проблемы.Декомпозиция систем на модули с отдельными интерфейсами, проверенными компилятором, была проблемой в Ada, C , C ++, CLU, Modula-3, и я уверен, во многих других языках.Основным преимуществом такой системы, как Standard ML или Caml, является то, что вы получаете явные подписи и модульную проверку типов (то, что сообщество C ++ в настоящее время борется с шаблонами и концепциями).Я подозреваю, что эти проблемы вечны и будут важны для любой большой системы, независимо от языка реализации.

5 голосов
/ 02 февраля 2010

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

0 голосов
/ 03 февраля 2010

Поток программы становится трудным для следовать быстрее, чем если бы Нефункциональный язык используется?

Это может иметь место, когда функциональный стиль поощряет программиста предпочитать мышление в терминах абстрактных, логических преобразований, отображая входные данные в выходные. Мышление в терминах «потока программы» предполагает последовательный режим работы с состоянием - и хотя функциональная программа может иметь последовательное состояние «под капотом», она обычно не структурирована вокруг этого.

Разницу в перспективе можно легко увидеть, сравнив императивный и функциональный подходы к «обработке сбора данных». Первый имеет тенденцию использовать структурированную итерацию, такую ​​как цикл for или while, сообщая программе «выполнить эту последовательность задач, затем перейти к следующей и повторять до завершения». Последний, как правило, использует абстрагированную рекурсию, например, функцию fold или map, сообщая программе "вот функция для объединения / преобразования элементов - теперь используйте ее". Нет необходимости следить за рекурсивным потоком программ через такую ​​функцию, как map; поскольку это абстракция без состояния, достаточно подумать о том, что это значит, а не о том, что он делает.

Возможно, что-то говорит о том, что функциональный подход медленно проникает в нефункциональные языки - рассмотрим foreach циклы, списочные представления Python ...

0 голосов
/ 03 февраля 2010

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

  1. Функциональное программирование ненавидит побочные эффекты.Вы действительно можете пометить разные слои слоями, и вы не будете бояться параллельной обработки ( модель актера , как в Erlang, действительно проще в использовании, чем блокировки и потоки).
  2. В культурном отношении,функциональный программист используется для разработки DSL для выражения и решения проблемы.Идентификация основных примитивов проблемы - это радикально иной подход, нежели стремление к совершенно новой модной структуре.
  3. Исторически в этой области работали очень умные люди: сборщик мусора, объектно-ориентированное, метапрограммирование ... Всеэти концепции были впервые реализованы на функциональной платформе.Существует множество литературы.

Но недостатком этих языков является то, что им не хватает поддержки и опыта работы в отрасли.Наличие переносимости, производительности и совместимости может быть реальной проблемой, когда на другой платформе, такой как Java, все это кажется очевидным.Тем не менее, язык, основанный на JVM, такой как Scala, может быть очень удачным для обеих сторон.

0 голосов
/ 02 февраля 2010

Обычно дело не в «функциональном», а в «процедурном»; это скорее ленивая оценка.

Ленивая оценка - это когда вы можете обрабатывать значения, фактически не вычисляя их; скорее, значение присоединяется к выражению, которое должно давать значение, если оно необходимо. Основным примером языка с ленивой оценкой является Haskell. Ленивая оценка позволяет определять и обрабатывать концептуально бесконечные структуры данных, так что это довольно круто, но это также несколько усложняет для человека-программиста внимательно следить за последовательностью вещей, которая действительно произойдет на его компьютере .

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

Без ленивых вычислений функциональные и процедурные языки допускают выражение одинаковых алгоритмов, с одинаковой сложностью и схожей «читабельностью». Функциональные языки имеют тенденцию ценить «чистые функции», то есть функции, которые не имеют побочных эффектов. Порядок оценки для чистой функции не имеет значения: в этом смысле чистые функции помогают программисту знать, что происходит, просто помечая части, для которых не важно знать, что происходит в каком порядке. Но это косвенное преимущество, и чистые функции также появляются в процедурных языках.

...