Чому функціональне програмування ще не прийняте?


197

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

  • Програми без громадянства; Побічних ефектів немає
  • Паралельність; Грає надзвичайно приємно завдяки зростаючій багатоядерній технології
  • Програми зазвичай коротші, а в деяких випадках простіші для читання
  • Продуктивність зростає (приклад: Erlang)

  • Імперативне програмування - це дуже стара парадигма (наскільки я знаю) і, можливо, не підходить для 21 століття

Чому компанії, що використовують або програми, написані на функціональних мовах, все ще такі "рідкісні"?

Чому, дивлячись на переваги функціонального програмування, ми все ще використовуємо імперативні мови програмування?

Може, це було ще рано для цього в 1990 році, але сьогодні?


1
ПРИМІТКА: це питання обговорювалося на мета щонайменше двічі, і єдиний консенсус полягає в тому, що його слід зберігати, хоч і архівувати через згаданий вище замок "історичної значущості". Я настійно закликаю тих, хто переглядає це, намагаючись розблокувати його, замість цього зупинитися і подякувати за те, що не потрібно брати участь у черговій набридливій дискусії з цього питання, насолоджуватися відповідними відповідями та продовжувати займатися своєю справою.
Shog9

Відповіді:


530

Тому що всі ці переваги - це і недоліки.

Програми без громадянства; Побічних ефектів немає

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

Коли концепції мови програмування принципово працюють проти модельованого домену, важко виправдати використання цієї мови.

Паралельність; Грає надзвичайно приємно завдяки зростаючій багатоядерній технології

Проблема просто штовхається. Завдяки незмінним структурам даних ви маєте дешеву безпеку ниток за рахунок можливо можливої ​​роботи з несвіжими даними. Завдяки структурам даних, що змінюються, ви маєте перевагу завжди працювати над новими даними ціною, щоб написати складну логіку, щоб зберегти дані. Це не так, як один із них, очевидно, кращий за інший.

Програми зазвичай коротші, а в деяких випадках простіші для читання

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

Продуктивність зростає (приклад: Erlang)

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

І пам’ятайте, ви не хочете викидати робочу систему; більшість програмістів не будують нові системи з нуля, а підтримують існуючі системи, більшість з яких були побудовані на нефункціональних мовах. Уявіть, що намагаєтесь виправдати це акціонерам. Чому ви брухтували існуючу працюючу систему оплати праці, щоб побудувати нову ціною мільйонів доларів? "Тому що функціональне програмування дивовижне" навряд чи порадує акціонерів.

Імперативне програмування - це дуже стара парадигма (наскільки я знаю) і, можливо, не підходить для 21 століття

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

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

Я будую компілятори для життя, і ми неодмінно використовуємо функціональний стиль для наступного покоління інструментів компілятора. Це тому, що функціональне програмування є принципово гарною відповідністю для різних проблем, з якими ми стикаємося. Наші проблеми полягають у використанні сировинної інформації - рядків та метаданих - та перетворенні їх у різні рядки та метадані. У ситуаціях, коли трапляються мутації, як хтось набирає IDE, проблемний простір по суті піддається функціональним методам, таким як поступова перебудова лише тих частин дерева, які змінилися. Багато доменів не мають цих приємних властивостей, які роблять їх очевидно придатними до функціонального стилю .


41
"Коли Джейн Сміт у бухгалтерському обліку виходить заміж і змінює своє ім'я на Джейн Джонс, база даних, що підтримує бізнес-процес, який друкує її зарплату, краще стосуватись такої мутації". З'явиться запис колишнього імені Джейн Сміт, ми не оновлюємо всі випадки колишнього імені Джейн на її нове ім’я;)
Джульєтта

40
@Juliet: Звичайно. Моя думка полягає в тому, що якщо у вас є об’єкт, який представляє працівника, має сенс думати про операцію "змінити ім'я працівника", щоб бути мутацією об'єкта, що представляє працівника , який не змінює ідентифікацію об'єкта . Коли Джейн Сміт змінює своє ім'я, ви не створюєте іншу службовцю, яку називають Джейн Джонс, яка інакше однакова. Немає двох працівників з двома різними іменами. Цілком природно моделювати цей процес як мутацію об'єкта, а не як побудову нового об’єкта.
Ерік Ліпперт

24
Це хороша відповідь, але я думаю, що ти часом перебільшуєш свою справу. Як сказала Джульєтта, хоча люди можуть вважати це зміною імені, це насправді є заміною імені на більш глибокому рівні. І хоча функціональні програми можуть бути важче для людей , щоб читати (бо це вивчений навик), то як правило , не тому , що вони більше. Програма Haskell майже завжди буде більш короткою, ніж, скажімо, програма Java - навіть у домені "погано підходить" з великою кількістю притаманного стану.
Чак

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

11
"Тому що всі ці переваги - це також недоліки. Програми без громадянства; Ніяких побічних ефектів": Наскільки я розумію (я недостатньо знаю ФП, щоб написати авторитетну відповідь), це не правильно . Функціональне програмування стосується референтної прозорості, а не уникнення стану (навіть якщо держава повинна оброблятися належним чином для забезпечення еталонної прозорості). Haskell дійсно дозволяє стан і мутацію. Він просто надає різні (можна сказати, кращі) інструменти для міркувань про це.
Джорджіо

38

Основні напрямки програмування: розмови з творцями основних мов програмування

[Haskell]

Чому, на вашу думку, жодна функціональна мова програмування не увійшла в мейнстрім?

Джон Х'юз: Поганий маркетинг! Я не маю на увазі пропаганду; у нас було багато цього. Я маю на увазі ретельний вибір цільової ринкової ніші для домінування з подальшими рішучими зусиллями зробити функціональне програмування далеко не найбільш ефективним способом вирішення цієї ніші. У щасливі дні 80-х років ми вважали, що функціональне програмування підходить для всього - але називати нову технологію "корисною для всього" - це те саме, що називати її "особливо хорошою ні за що". Яким повинен бути бренд? Це проблема, яку Джон Лаунберій дуже чітко описав у запрошеній до розмови на ICFP. Galois Connections ледь не піддався, коли їхній бренд був "програмним забезпеченням на функціональних мовах", але вони перейшли від сили до міцності, зосередившись на "програмному забезпеченні високої надійності".

Багато людей не мають уявлення про те, як відбуваються технологічні інновації, і сподіваються, що кращі технології просто стануть домінуючими самі по собі ефект "кращої мишоловки" ), але у світі просто не так.


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

перейдіть за посиланням і прочитайте відгуки про досить кумедний розваг Grady Booch. Поняття не маю хто Бух, але все одно це змусило мене кохатись.
fearofawhackplanet

4
Зрештою, Грейді Бух відповідає разом з Джейкобсоном та Румбо за гидоту, що є UML.
ДАЙТЕ МОЕ правильне ДУМКА

27

Відповідь запасу полягає в тому, що ні замінити, ні іншим буде, ні вони повинні - це різні інструменти, які мають різні набори плюсів і мінусів, і який підхід має перевагу, буде відрізнятися залежно від проекту та інших "м'яких" питань, таких як наявний пул талантів.

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

Я думаю, що сьогодні це рідко, тому що більшість сучасних професійних талановитих колективів найбільше комфортні з імперативними та об'єктно-орієнтованими технологіями. Наприклад, я не раз вибирав Java як мову для комерційного проекту, тому що вона була досить хорошою, не суперечливою, і я знаю, що у мене ніколи не вийде людей, які можуть програмувати (досить добре) в ній.


Це дуже проникливо і чудово прагматично. Однозначно найкраща відповідь, яку я бачив на це питання у всіх його формах.
Бенсон

Можливо, мовою, якою обидва є громадянами першого класу, стане популярним.
Кевін Костлан

1
Погодьтеся 110%. Кілька разів я намагався потрапити в ПП, але через кілька тижнів втратив бажання продовжувати. Я програмую процедурно понад 30 років, і я занадто звик до імперативного програмування. Це стосується ІТ-галузі в цілому. Зміни не прийдуть легко і не швидко.
Річард Енг

26

Незважаючи на переваги функціонального програмування, імперативне та об’єктно-орієнтоване програмування ніколи не закінчиться повністю.

Імперативне та об’єктно-орієнтоване програмування - це покроковий опис проблеми та її рішення. Як таке, це може бути легше зрозуміти. Функціональне програмування може бути дещо незрозумілим.

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

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


3
Хіба OOP не є якимось підмножиною імперативного програмування?
панкрекса

9
OOP - суперсет. OOP необхідний, оскільки C ++ - C.
Роберт Харві

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

9
Мови ОО, як правило, є обов'язковими, але не повинні бути. OCaml - це сильна (хоча і не суто) функціональна мова, весь її основна причина є ОО.
Чак

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

21

Чи не так?

Малі розмови були чудовою об'єктно-орієнтованою системою ще в той час. Чому об’єктно-орієнтоване програмування не прийняте? Ну, є. Це просто не схоже на Smalltalk. Основні мови продовжують набирати більше Smalltalk, як C ++, Java, C #, і т. Д. Мода та стиль змінюються повільніше, ніж будь-що, тому, коли OO перейшла в мейнстрім, ми отримали це, склеївши частини OO на старі мови, так що це виглядало досить, як C, щоб проковтнути .

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


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

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

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 (лише декілька прикладів), але можу прочитати будь-яку з них досить добре - майже так само, як і люди, які ними користуються щодня.

Щодо функціональної сторони, це набагато менш вірно. Наприклад, я можу також написати схему досить розумно, але це мало користі при читанні Ocaml або Haskell (лише для кількох прикладів). Навіть у межах однієї сім'ї (наприклад, схема проти, звичайний Lisp) знайомство з одним не здається майже таким же перекладним для іншого.

Твердження про те, що функціональний код є більш читабельним, як правило, відповідає дійсності лише у вузькому діапазоні умов. Для людей, які надзвичайно добре знайомі з мовою, читабельність справді є чудовою - але для всіх інших вона часто поруч із неіснуючою. Гірше, хоча розбіжності в процедурних мовах значною мірою є синтаксисом, а тому відносно легко засвоюються, відмінності у функціональних мовах часто набагато більш фундаментальні, тому вони потребують значного вивчення, щоб реально зрозуміти (наприклад, знання Ліспа мало допомагає в розумінні Монад).

Інший головний момент полягає в тому, що ідея про те, що функціональні програми коротші, ніж процедурні, часто базується більше на синтаксисі, ніж на семантиці. Програми, написані в Haskell (для одного прикладу), часто є досить короткими, але його функціональність є досить малою частиною цього. Дуже багато, якщо просто Хаскелл має відносно короткий синтаксис.

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


Відмінний коментар! Я погоджуюся від усієї душі. Я вважаю більшість процедурних мов досить легко читати та розуміти, хоча я є лише сумлінним експертом у кількох з них. Не можу сказати те саме про мови FP.
Річард Енг

1
Ще одним важливим моментом є те, що в будь-якій заданій парадигмі ви знайдете цілий спектр знань - від новачків до гуру. 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 років. Попросити розробників прийняти нові раціонально налаштовані умови мислення, але це просто потребує часу (багато-багато років). Наприклад, OOP дійсно отримав основне використання на початку 1980-х. Однак вона не отримала спокою до кінця 1990-х.
  2. Потрібно, щоб люди були змушені стикатися з силою технології, перш ніж вона стане великою . Наразі люди користуються інструментами, які не використовують паралелізм і все працює нормально. Коли програми, які не використовують паралелізм, стають нестерпно повільними; тоді багато людей будуть змушені використовувати паралелізм-інструменти, і FP може набути популярності. Це також може стосуватися інших сильних сторін FP.

3
FP дуже хороший у використанні коду. Можливо, краще, ніж ОО. Мені довелося зіткнутися з цим на роботі кілька разів, мігруючи до різних типів, і нова система, і це було безболісно.
nlucaroni

@Freddy Rios та @nlucaroni. Я переформулював коментар, щоб усунути неправильне тлумачення.
Філ
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.