Почему еще не занято функциональное программирование?


197

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

  • Программы без гражданства; Нет побочных эффектов
  • Параллелизм; Очень хорошо играет с растущей многоядерной технологией
  • Программы обычно короче, а в некоторых случаях их легче читать
  • Производительность повышается (пример: Эрланг)

  • Императивное программирование - очень старая парадигма (насколько я знаю) и, возможно, не подходящая для 21-го века

Почему компании или программы, написанные на функциональных языках, все еще так «редки»?

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

Может быть, это было слишком рано в 1990 году, но сегодня?


1
ПРИМЕЧАНИЕ: этот вопрос обсуждался в мета-версии, по крайней мере, дважды, и единодушным является то, что его следует сохранить, хотя и заархивировать через блокировку «исторического значения», упомянутую выше. Я настоятельно призываю всех, кто рассматривает это, чтобы открыть его, чтобы вместо этого остановиться и поблагодарить за то, что вам не пришлось участвовать в очередной утомительной дискуссии по этому вопросу, наслаждаться ответами, как они есть, и заниматься своими делами.
Shog9

Ответы:


530

Потому что все эти преимущества также являются недостатками.

Программы без гражданства; Нет побочных эффектов

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

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

Параллелизм; Очень хорошо играет с растущей многоядерной технологией

Проблема просто решена. С неизменяемыми структурами данных вы получаете дешевую безопасность потоков за счет возможной работы с устаревшими данными. Благодаря изменяемым структурам данных вы всегда можете работать с свежими данными за счет необходимости написания сложной логики для обеспечения согласованности данных. Это не похоже на то, что один из них явно лучше другого.

Программы обычно короче, а в некоторых случаях их легче читать

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

Производительность повышается (пример: Эрланг)

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

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

Императивное программирование - очень старая парадигма (насколько я знаю) и, возможно, не подходящая для 21-го века

Функциональное программирование тоже очень старое. Я не понимаю, насколько важен возраст концепции.

Не пойми меня неправильно. Я люблю функциональное программирование, я присоединился к этой команде, потому что хотел помочь перенести концепции функционального программирования в C #, и я думаю, что программирование в неизменном стиле - это путь будущего. Но программирование в функциональном стиле сопряжено с огромными издержками, от которых просто невозможно избавиться. Переход к более функциональному стилю будет происходить медленно и постепенно в течение десятилетий. И это то, что будет: переход к более функциональному стилю, а не массовое признание чистоты и красоты Haskell и отказ от C ++.

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


41
«Когда Джейн Смит в бухгалтерии выходит замуж и меняет свое имя на Джейн Джонс, база данных, поддерживающая бизнес-процесс, который печатает ее зарплату, должна быть направлена ​​на обработку такого рода мутаций». Будет запись прежнего имени Джейн Смит, мы не будем задним числом обновлять все экземпляры прежнего имени Джейн до ее нового имени;)
Джульетта

40
@Juliet: Конечно. Я хочу сказать, что если у вас есть объект, представляющий сотрудника, имеет смысл думать, что операция «изменить имя сотрудника» является мутацией объекта, представляющего сотрудника , который не меняет идентичность объекта . Когда Джейн Смит меняет свое имя, вы не создаете другого сотрудника по имени Джейн Джонс, который в остальном будет таким же. Нет двух сотрудников с двумя разными именами. Естественно моделировать этот процесс как мутацию объекта, а не как конструкцию нового объекта.
Эрик Липперт

24
Это хороший ответ, но я думаю, что вы иногда преувеличиваете свое дело. Как сказала Джульетта, хотя люди могут думать об этом как об изменении имени, на самом деле это замена имени на более глубоком уровне. И хотя функциональные программы могут быть тяжелее для людей , чтобы читать (потому что это изученный навык), то как правило , не потому , что они больше. Программа на Haskell почти всегда будет более краткой, чем, скажем, программа на Java - даже в «плохо подходящей» области с большим количеством присущего ей состояния.
Чак

29
+1 Это был такой глоток свежего воздуха, чтобы прочитать этот ответ. Фантастически слышать такой прагматизм (со страстью к функциональному программированию) от кого-то на вашей должности.
Dhaust

11
«Потому что все эти преимущества также являются недостатками. Программы без состояния; никаких побочных эффектов»: насколько я понимаю (я не знаю достаточно о FP, чтобы написать авторитетный ответ), это не правильно . Функциональное программирование подразумевает ссылочную прозрачность, а не избегание состояния (даже если состояние должно обрабатываться соответствующим образом для обеспечения ссылочной прозрачности). Haskell допускает состояние и мутации. Он просто предоставляет различные (можно утверждать, лучше) инструменты для рассуждений об этом.
Джорджио

38

Создатели программирования: беседы с создателями основных языков программирования

[Haskell]

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

Джон Хьюз: Плохой маркетинг! Я не имею в виду пропаганду; у нас было много этого. Я имею в виду тщательный выбор доминирующей ниши целевого рынка, за которой следует решительная попытка сделать функциональное программирование наиболее эффективным способом решения этой ниши. В счастливые дни 80-х годов мы думали, что функциональное программирование хорошо для всех, но называть новую технологию «хорошей для всего» - это то же самое, что называть ее «особенно хорошей ни в чем». Каким должен быть бренд? Это проблема, которую Джон Лончбери очень четко описал в своем выступлении в ICFP. Galois Connections едва не обанкротились, когда их бренд был «программным обеспечением на функциональных языках», но они набирают силу с тех пор, как сосредоточились на «высоконадежном программном обеспечении».

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


36
Haskell: через 20 лет успех за одну ночь!
Джульетта

перейдите по ссылке и прочитайте обзоры довольно забавного диска Грэди Буча. Понятия не имею, кто такой Буч, но это все равно заставило меня смеяться.
fearofawhackplanet

4
В конечном счете, вместе с Якобсоном и Румбо, Грэди Буч отвечает за мерзость, которая является UML.
ПРОСТО МОЕ правильное мнение

27

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

Я думаю, вы правы, что рост параллелизма за счет многоядерности увеличит процент (от глобального набора проектов разработки), когда функциональное программирование будет выбрано над другими стилями.

Я думаю, что сегодня это редкость, потому что большинство сегодняшних профессиональных кадров талантливее всего чувствуют себя комфортно с объектно-ориентированными технологиями. Например, я не раз выбирал Java в качестве языка для коммерческого проекта, потому что он был достаточно хорошим, не спорным, и я знаю, что у меня никогда не останется людей, которые могут (достаточно хорошо) программировать на нем.


Это очень проницательно и восхитительно прагматично. Определенно лучший ответ, который я видел на этот вопрос во всех его формах.
Бенсон

Может быть, на языке, для которого оба первоклассные граждане станут популярными.
Кевин Костлан

1
Согласен 110%. Несколько раз я пытался попасть в FP, но потерял желание продолжать через несколько недель. Я программировал более 30 лет, и я слишком привык к императивному программированию. Это верно для ИТ-индустрии в целом. Изменения не придут легко и быстро.
Ричард Энг,

26

Несмотря на преимущества функционального программирования, императивное и объектно-ориентированное программирование никогда не исчезнет полностью.

Императивное и объектно-ориентированное программирование - это пошаговое описание проблемы и ее решения. Таким образом, это может быть легче понять. Функциональное программирование может быть немного неясным.

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

Современное состояние дел заключается в том, что императивные языки (такие как C #) заимствуют функции из функционального мира (например, лямбда-выражения) и наоборот.


3
Разве ООП не является своего рода подмножеством императивного программирования?
pankrax

9
ООП - это суперсет. ООП является императивом, как С ++ - С.
Роберт Харви

10
Я не думаю, что ООП обязательно зависит от императивного программирования. Посмотрите Clojure или CLOS - оба функциональны, но объектно-ориентированы.
Гейб

9
ОО языки, как правило, являются обязательными, но не обязательно. OCaml - это сильно (хотя и не чисто) функциональный язык, смыслом которого является OO.
Чак

7
Я не понимаю, почему ООП является надмножеством императивного программирования. Не весь императивный код является ООП, и не весь функциональный код не является ООП. Я бы скорее сказал, что ООП относится к императивному программированию и функциональному программированию, как аэродинамические крылья, к гоночным автомобилям, или самолетам, или ракетам, или охлаждающим вентиляторам, или ветряным мельницам, или ... т.е. концепции связаны, но не тесно связаны между собой. соединение 1-к-1.
Себастьян Мах

21

Не так ли?

Smalltalk был отличной объектно-ориентированной системой того времени. Почему объектно-ориентированное программирование не вступило во владение? Ну, это так. Это просто не похоже на Smalltalk. Основные языки продолжают становиться более похожими на Smalltalk с C ++, Java, C # и т. Д. Мода и стиль меняются медленнее, чем что-либо другое, поэтому, когда ОО стало массовым, мы получили его, приклеив части ОО к старым языкам, чтобы он выглядел достаточно, как С, чтобы проглотить ,

Функционально так же. Хаскель был отличным функциональным языком. Но сегодня у нас еще больше массовых программистов, использующих C-подобный синтаксис, чем 20 лет назад. Так что это должно выглядеть как C. Готово: посмотрите на любое выражение LINQ и скажите, что оно не работает.


2
Интересный момент, но как основные языки стали более похожими на Smalltalk? Например, C ++, Java и C # не основаны на отправке сообщений, что (я считаю) является наиболее важной частью парадигмы Smalltalk.
Джонатан Стерлинг

4
Джонатан: Выберите любую функцию Smalltalk и посмотрите, как она слабее в C ++ (самая старая), хорошо в Java и лучше в C #. Например, GC (только Java / C #), автобокс (позднее только Java / C #), замыкания (только C #) и рефлексия (присутствует в Java, лучше в C #). Если вы хотите передавать сообщения, посмотрите на C # 4 dynamic. Это самая Smalltalk-y из этих функций, поэтому для меня не удивительно, что она присутствует только в последней версии самого современного из этих трех языков. :-)
Кен

Javascript, python и ruby ​​являются хорошими иллюстрациями того, как это действительно имеет место
nafg

15

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

Один из авторов сказал, что императивный код легче понять, чем функциональный программный код. Это верно только в том случае, если читатель уже видел императивный код, особенно если предыдущие примеры являются частью одного и того же «семейства» (например, C / C ++, Perl, PHP и Java). Я бы не стал утверждать, что это верно для любого императивного языка; возьмите сравнение Java и Forth, чтобы сделать крайний пример.

Для непрофессионала все языки программирования являются непонятным бредом, за исключением, может быть, многословных языков, таких как Hypertalk и SQL. (Следует отметить, что SQL является декларативным и / или функциональным языком и пользуется огромной популярностью.)

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


«Один из авторов сказал, что императивный код легче понять, чем код функционального программирования. Это верно только в том случае, если читатель уже видел императивный код, особенно если предыдущие примеры являются частью одного и того же« семейства »(например, C / C ++, Perl, PHP и Java). ": Совершенно верно (+1): я помню, сколько усилий мне пришлось приложить для изучения Pascal и C, когда я начал программировать. И как легко читать Scala, Haskell или Scheme сейчас, когда у меня есть некоторый опыт работы с этими языками.
Джорджио

2
Единственная причина, почему я все еще считаю изменчивое состояние полезным иногда, состоит в том, что он предлагает простой способ написания быстрого кода (без копирования); но причиной этого может быть то, что я не знаю достаточно функционального программирования и что в 90% случаев вы можете написать быстрый функциональный код без использования изменяемого состояния.
Джорджио

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

14

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

Во-первых, и (на мой взгляд), процедурные языки значительно выиграли от степени их общности. Например, почти любой, кто знает практически любой из основных процедурных (или ОО) языков, практически в любой степени, может достаточно хорошо читать большинство других. Я активно избегаю работать на Java, C #, Cobol, Fortran или Basic (всего лишь для нескольких примеров), но могу читать любой из них достаточно хорошо - практически также, как люди, которые используют их каждый день.

С функциональной стороны это гораздо менее верно. Например, я могу написать достаточно разумно Scheme, но это мало что дает для чтения Ocaml или Haskell (только для пары примеров). Даже в пределах одной семьи (например, Scheme vs. Common Lisp) знакомство с одной, похоже, не слишком хорошо переводится на другую.

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

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

Немногие чисто функциональные языки могут успешно конкурировать с APL за краткий исходный код (хотя, честно говоря, APL также поддерживает создание функций более высокого уровня, так что разница не так велика, как в некоторых других случаях). Наоборот, Ada и C ++ (только для пары примеров) могут быть довольно конкурентоспособными с точки зрения количества операций, необходимых для выполнения данной задачи, но синтаксис (по крайней мере, обычно) значительно более многословен.


Отличный комментарий! Я согласен от всего сердца. Я считаю, что большинство процедурных языков довольно легко читать и понимать, хотя я только добросовестный эксперт в некоторых из них. Не могу сказать то же самое о языках FP.
Ричард Энг,

1
Другим важным моментом является то, что в любой данной парадигме вы найдете широкий спектр знаний, от новичков до гуру. Код FP может быть легко читаемым и понятным для экспертов, но программисты среднего уровня могут все еще испытывать трудности. Эксперты обычно составляют очень небольшую часть сообщества FP.
Ричард Энг,

11

Нет воспринимаемой необходимости

Я вспоминаю ответ моего старого босса Рика Клайна, когда я показал ему копию лекции Джона Бэкуса «Премия Тьюринга» под названием « Можно ли освободить программирование от стиля фон Неймана»?

Его ответ: «Может быть, некоторые из нас не хотят быть освобожденными от стиля фон Неймана!»


10

Почему еще не занято функциональное программирование?

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

Программы без гражданства; Нет побочных эффектов

Программы без состояния легче тестировать. В настоящее время это широко ценится и часто используется в промышленности.

Параллелизм; Очень хорошо играет с растущей многоядерной технологией. Программы обычно короче, а в некоторых случаях их легче читать. Производительность повышается (пример: Erlang)

Вы объединяете параллелизм и параллелизм.

Параллелизм может быть эффективно реализован с использованием последовательных процессов связи (CSP). Код внутри CSP может изменять его локальное состояние, но сообщения, передаваемые между ними, всегда должны быть неизменными.

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

Почему компании или программы, написанные на функциональных языках, все еще так «редки»?

Scala часто рассматривается как функциональный язык, но он не более функциональный, чем C #, который сегодня является одним из самых популярных языков в мире.

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

Чисто функциональное программирование имеет много серьезных недостатков, поэтому мы используем нечистые функциональные языки, такие как Lisp, Scheme, SML, OCaml, Scala и C #.


7

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

  1. Чтобы получить все преимущества функционального программирования, вам нужна лень. Да, существуют строгие функциональные языки, но реальные преимущества функционального программирования не так уж хороши в строгом коде. Например, в Haskell легко создать последовательность ленивых операций над списком, объединить их и применить к списку. Например. op1 $ op2 $ op3 $ op4 $ someList, Я знаю, что он не собирается строить весь список, и внутренне я собираюсь получить хороший цикл, который проходит по элементам по одному. Это позволяет вам писать действительно модульный код. Интерфейс между двумя модулями может включать передачу потенциально обширных структур данных, и все же вам не нужно иметь резидентную структуру.

  2. Но когда вам лень, становится трудно рассуждать об использовании памяти. Изменение флагов компилятора Haskell часто изменяет объем памяти, используемой алгоритмом, с O (N) на O (1), за исключением того, что иногда это не так. Это не совсем приемлемо, когда у вас есть приложения, которым нужно максимально использовать всю доступную память, и это не очень хорошо даже для приложений, которым не нужна вся память.


Лень также менее чем идеально взаимодействует с отладкой.
Брайан

3
Поскольку я обнаружил, что многие ошибки, которые я преследую на других языках, связаны с отсутствием ссылочной прозрачности, я меньше беспокоюсь о проблемах отладки, хотя иногда они могут быть болезненными.
Sigfpe

6

Две вещи:

  1. Это просто занимает время, независимо от того, насколько хороша технология. Идеям, стоящим за ФП, около 70 лет. Но его основное использование в разработке программного обеспечения (в окопах, в промышленности), вероятно, составляет менее 10 лет. Просить разработчиков принять расово новое мышление возможно, но это занимает много времени (много-много лет). Например, ООП действительно получил широкое распространение в начале 1980-х годов. Однако до конца 1990-х годов он не приобретал господства.
  2. Нужно, чтобы люди были вынуждены столкнуться с силой технологии, прежде чем она достигнет большого успеха . В настоящее время люди используют инструменты, которые не используют параллелизм, и все работает хорошо. Когда приложения, которые не используют параллелизм, становятся невыносимо медленными; тогда многие люди будут вынуждены использовать инструменты параллелизма, и популярность FP может возрасти. Это может также относиться к другим сильным сторонам FP.

3
FP очень хорош в повторном использовании кода. Наверное, лучше, чем ОО. Мне приходилось сталкиваться с этим на работе несколько раз, переходя на разные типы и новую систему, и это было безболезненно.
nlucaroni

@ Фредди Риос и @nlucaroni. Я перефразировал комментарий, чтобы устранить неверное толкование.
Фил
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.