Ловушки/Недостатки Функционального программирования [закрываются]

Мой опыт состоит в том, что большинство людей использует одни буквы, например: i, j, k... или x, y, или r, c (для строки/столбец) или w, h (для ширины/высоты), и т.д.

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

// recommended style              ●    // "typical" single-letter style
                                  ●
for (ii=0; ii<10; ++ii) {         ●    for (i=0; i<10; ++i) {
    for (jj=0; jj<10; ++jj) {     ●        for (j=0; j<10; ++j) {
        mm[ii][jj] = ii * jj;     ●             m[i][j] = i * j;
    }                             ●        }
}                                 ●    }

В случае, если преимущество не сразу очевидно: поиск кода для любой одной буквы найдет много вещей, которые не являются , что Вы ищете. Буква i происходит довольно часто в коде, где это не переменная, Вы ищете.

68
задан Community 23 May 2017 в 12:02
поделиться

7 ответов

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

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

(Спасибо Джареду Апдайку за предложение списка различий.)

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

(Спасибо Джареду Апдайку за предложение списка различий.)

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

(Спасибо Джареду Апдайку за предложение списка различий.)

29
ответ дан 24 November 2019 в 14:10
поделиться

Если ваш язык не предоставляет хороших механизмов для определения поведения состояния / исключения через вашу программу (например, синтаксические сахара для монадических привязок), то любая задача, связанная с состоянием / исключениями, становится рутиной. (Даже с этими сахарами некоторым людям может быть труднее иметь дело с состоянием / исключениями в FP.)

Функциональные идиомы часто делают много инверсии контроля или лени, что часто оказывает негативное влияние на отладку (использование отладчик). (Это несколько компенсируется тем, что FP гораздо менее подвержен ошибкам из-за неизменности / ссылочной прозрачности, что означает, что вам придется отлаживать реже.)

23
ответ дан 24 November 2019 в 14:10
поделиться

Филип Вадлер написал об этом статью (под названием «Почему никто не использует функциональные языки программирования») и рассмотрел практические ловушки, мешающие людям использовать языки программирования FP:

Обновить : недоступна старая ссылка для тех, у кого есть доступ к ACM:

13
ответ дан 24 November 2019 в 14:10
поделиться

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

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

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

    Обычно экспертам не составляет труда писать быстрые функциональные программы; и на самом деле некоторые из наиболее эффективных параллельных программ на 8- и 16-ядерных процессорах теперь написаны на Haskell .

  • Более вероятно, что кто-то, начинающий функциональное программирование, сдастся до того, как осознает обещанную производительность выигрывает, чем тот, кто начинает, скажем, Python или Visual Basic. Просто не так много поддержки в виде книг и инструментов разработки.

  • Стало меньше людей, с которыми можно было бы поговорить. Stackoverflow - хороший пример; относительно немного программистов на Haskell посещают сайт регулярно (хотя отчасти это связано с тем, что у программистов на Haskell есть свои собственные оживленные форумы, которые намного старше и лучше устоявшихся, чем Stackoverflow).

    Также верно, что вы можете ' Очень легко разговаривать со своим соседом, потому что концепциям функционального программирования труднее научить и труднее выучить, чем объектно-ориентированные концепции, лежащие в основе таких языков, как Smalltalk, Ruby и C ++. Кроме того, объектно-ориентированное сообщество потратило годы на разработку хороших объяснений того, что они делают, в то время как сообщество функционального программирования, похоже, считает, что их материал, безусловно, великолепен и не требует каких-либо специальных метафор или словаря для объяснения. (Они ошибаются. Я все еще жду первую большую книгу Функциональные шаблоны проектирования . )

  • Хорошо известным недостатком ленивого функционального программирования (применимого к Haskell или Clean, но не к ML, Scheme или Clojure) является то, что очень сложно предсказать затраты времени и пространства. оценить ленивую функциональную программу - даже эксперты не могут этого сделать. Эта проблема является фундаментальной для парадигмы и никуда не денется. Есть отличные инструменты для определения поведения времени и пространства постфактум , но чтобы использовать их эффективно, вы должны уже быть экспертом.

46
ответ дан 24 November 2019 в 14:10
поделиться

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

(Написано на SMLnj. Также, пожалуйста, извините за несколько надуманный пример.)

datatype Animal = Dog | Cat;

fun happyNoise(Dog) = "pant pant"
  | happyNoise(Cat) = "purrrr";

fun excitedNoise(Dog) = "bark!"
  | excitedNoise(Cat) = "meow!";

Я могу очень быстро добавить следующее:

fun angryNoise(Dog) = "grrrrrr"
  | angryNoise(Cat) = "hisssss";

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

datatype Animal = Dog | Cat | Chicken;

fun happyNoise(Dog) = "pant pant"
  | happyNoise(Cat) = "purrrr"
  | happyNoise(Chicken) = "cluck cluck";

fun excitedNoise(Dog) = "bark!"
  | excitedNoise(Cat) = "meow!"
  | excitedNoise(Chicken) = "cock-a-doodle-doo!";

fun angryNoise(Dog) = "grrrrrr"
  | angryNoise(Cat) = "hisssss"
  | angryNoise(Chicken) = "squaaaawk!";

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

8
ответ дан 24 November 2019 в 14:10
поделиться

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

Я изучал класс свертки функций сейчас на три дня. У Fold, похоже, очень простое приложение: взять список и сократить его до одного значения. Haskell реализует для этого foldl и foldr . Эти две функции имеют совершенно разные реализации. Существует альтернативная реализация foldl , которая называется foldl . Вдобавок к этому существует версия с немного другим синтаксисом под названием foldr1 и foldl1 с разными начальными значениями. Из которых существует соответствующая реализация foldl1 ' для foldl1 . Как будто все это не сногсшибательно, функции, которые сворачивают [lr]. * требуют в качестве аргументов и используются внутри при сокращении, имеют две отдельные сигнатуры, только один вариант работает с бесконечными списками (r) , и только один из них выполняется в постоянной памяти (как я понимаю (L), потому что только он требует редекс ). Понимание того, почему foldr может работать с бесконечными списками, требует, по крайней мере, приличного понимания языков lazy-behaviorvoir и той незначительной детали, что не все функции заставляют вычислять второй аргумент. Графики этих функций в Интернете чертовски сбивают с толку человека, который никогда не видел их в колледже. Не существует эквивалента perldoc . Я не могу найти ни одного описания того, что делает какая-либо из функций в прелюдии Haskell. Prelude - это своего рода предустановленный дистрибутив с ядром. На самом деле мой лучший ресурс - это парень, которого я никогда не встречал (Кейл), который помогает мне за огромные деньги в свое время.

О, и фолд не должен сводить список к скаляру не-списочного типа. , функция идентичности для списков может быть записана foldr (:) [] [1,2,3,4] (подчеркивает, что вы можете накапливать список).

/ me возвращается к чтению .

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

О, и фолд не должен сводить список к скаляру не-списочного типа. , функция идентичности для списков может быть записана foldr (:) [] [1,2,3,4] (подчеркивает, что вы можете накапливать список).

/ me возвращается к чтению .

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

О, и фолд не должен сводить список к скаляру не-списочного типа. , функцию идентичности для списков можно записать в виде foldr (:) [] [1,2,3,4] (подчеркивает, что вы можете накапливать список).

/ me возвращается к чтению .

3
ответ дан 24 November 2019 в 14:10
поделиться

Вот некоторые проблемы, с которыми я столкнулся:

  1. Большинство людей находят функциональное программирование трудным для понимания. Это означает, что вам, вероятно, будет труднее написать функциональный код, и почти наверняка будет труднее его усвоить.
  2. Функциональные языки программирования обычно медленнее, чем такие языки, как c. Со временем это становится менее серьезной проблемой (потому что компьютеры становятся быстрее, а компиляторы - умнее)
  3. Не так широко, как их обязательные аналоги, может быть трудно найти библиотеки и примеры для общих проблем программирования. (Например, почти всегда легче найти что-то для Python, чем для Haskell)
  4. Не хватает инструментов, особенно для отладки. Это определенно не так просто, как открыть Visual Studio для C #, или eclipse для Java.
2
ответ дан 24 November 2019 в 14:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: