Читання функціонального програмування [закрито]


13

Мені це цікаво, тому що я пам'ятаю, перш ніж вивчати будь-які функціональні мови, я вважав їх усі жахливо, жахливо, жахливо нечитабельними. Тепер, коли я знаю Haskell і f #, я вважаю, що потрібно трохи більше часу читати менше коду, але цей маленький код робить набагато більше, ніж еквівалентна сума, необхідною мовою, так що це відчуває чистий прибуток, і я не дуже практикується у функціоналі.

Ось моє питання, я постійно чую від OOP людей, що функціональний стиль жахливо не читається. Мені цікаво, якщо це так, і я оманлюю себе, чи якби вони зайняли час, щоб вивчити функціональну мову, весь стиль не був би більш нечитабельним, ніж OOP?

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


1
Я пам’ятаю, як дивився на код «Супер Наріо Братів» svn.coderepos.org/share/lang/haskell/nario, коли я ледве нічого знав про функціональне програмування і пам’ятаю, що думав: «Вау. Це здається по-справжньому зрозумілим '
WuHoUnited



3
@BlackICE linq та lambdas - це далеко не визначення "функціонального програмування". Функціональне програмування частіше за все включає системи типів, оскільки, коли ви починаєте розпізнавати функції як типи, а не просто об'єкти / класи / записи як типи, ви отримуєте цілу масу нових здібностей та прийомів. Вираз LINQ та Lambda (або монада списку та функції вищого порядку) - це лише дві конкретні результати, з яких є багато інших.
Джиммі Хоффа

Відповіді:


15

Читання коду дуже суб'єктивне . Через це різні люди вважають один і той же код читабельним чи нечитабельним.

Завдання x = x + 1звучить дивно для математика, оскільки завдання виглядає в омані схожим на порівняння.

Простий шаблон дизайну OOP був би абсолютно незрозумілим для тих, хто не знайомий з цими шаблонами. Розглянемо одиночну . Хтось запитав: "Навіщо мені потрібен приватний конструктор? Який загадковий метод getInstance() ? Чому ми не зробимо глобальну змінну і не призначимо там об'єкт?"

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

Сказавши це, слід розуміти, що ПП - це не срібна куля. Є багато додатків, де FP було б важко застосувати, і, отже, це призведе до гіршого читання коду .


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

12

Коротка відповідь:

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

Довга відповідь:

Саме функціональне програмування не може бути читабельним чи нечитабельним, оскільки це парадигма, а не стиль написання коду. Наприклад, у C # функціональне програмування виглядає так:

return this.Data.Products
    .Where(c => c.IsEnabled)
    .GroupBy(c => c.Category)
    .Select(c => new PricesPerCategory(category: c.Key, minimum: c.Min(d => d.Price), maximum: c.Max(d => d.Price)));

і вважається читабельною будь-яка людина, яка має достатній досвід роботи на Java, C # або подібних мовах.

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

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

Порівняйте:

public void IsWithinRanges<T>(T number, param Range<T>[] ranges) where T : INumeric
{
    foreach (var range in ranges)
    {
        if (number >= range.Left && number <= range.Right)
        {
            return true;
        }
    }

    return false;
}

до:

public function void IsWithinRanges
    with parameters T number, param array of (Range of T) ranges
    using generic type T
    given that T implements INumeric
{
    for each (var range in ranges)
    {
        if (number is from range.Left to range.Right)
        {
            return true;
        }
    }

    return false;
}

Таким же чином:

var a = ((b - c) in 1..n) ? d : 0;

може бути виражена уявною мовою як:

define variable a being equal to d if (b minus c) is between 1 and n or 0 otherwise;

Коли коротший синтаксис краще?

У той час як більш багатослівний синтаксис легше зрозуміти для початківця, більш компактний синтаксис легше для досвідчених розробників. Коротший код означає менше символів для набору, що означає більшу продуктивність.

Тим більше, що насправді не має сенсу змушувати людину вводити ключове слово, щоб вказати щось, що може бути виведено із синтаксису.

Приклади:

  • У PHP потрібно вводити functionперед кожною функцією чи методом, без конкретних причин це робити.

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

  • Синтаксис 1..n, який використовується в багатьох FP (і Matlab), може бути замінений between 1, nабо between 1 and nабо between (1, n). betweenКлючове слово робить його набагато легше зрозуміти , для людей , які не знайомі з синтаксисом мови, але все - таки, дві точки набагато швидше набрати.


8
Я згоден з настроями, але з різних причин. Справа не в тому, як легко експерт може написати код, оскільки код зазвичай читається набагато частіше, ніж написаний. Більш короткий код також може допомогти читати, не витрачаючи дорогоцінний час, простір на екрані та розумові здібності, якщо щось було б очевидно з більш короткого показника (наприклад, нові рядки замість крапки з комою; ці два збіги все одно). Він також може зашкодити, коли він стає занадто криптовалютним (наприклад, я віддаю перевагу for x in xsнад for x xs, тому що це допомагає мені розрізняти змінну циклу та контейнер).

Багато людей, на яких я скаржаться на FP, скаржаться також на фрагмент C #, який ви вказали, як ви сказали, це також приклад FP. Можливо, це більше питання моїх колег, ніж читабельність, якщо більшість людей з ООП вважають цей фрагмент читабельним, хоча я не повністю переконаний, що більшість людей з ООП роблять із мого досвіду .. тому я відчуваю себе настільки невпевненим у цій темі.
Джиммі Хоффа

@Jimmy Hoffa: Див. Programmers.stackexchange.com/a/158721/6605, де я обговорюю саме фрагмент C # та те, як він сприймається початківцями програмістами.
Арсеній Муренко

1
@Sergiy: у Java або C # підпис методу не містить methodу ньому ключового слова. Приклад: public int ComputePrice(Product product). Додавання такого ключового слова, як те, що зробив PHP, просто додає безладу, а не полегшує читання. Якщо програміст не в змозі зрозуміти, що функція є функцією з її підпису, або цей програміст не має жодного досвіду, або код набагато нечитабельніший, ніж найгірший код, який я коли-небудь бачив.
Арсеній Муренко

1
@Sergiy: Є випадки, коли багатослівність може допомогти (інакше ми побачили б такі мови та код p i ComputePrice(product): _.unitPrice * ~.cart[_]), але деякі мови підштовхують її занадто далеко. Приклад зайвого functionключового слова в PHP - хороший приклад.
Арсеній Муренко

6

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

Наприклад, для функціонального програміста закономірно написати код, який може вийти з ладу в різних точках Maybeмонади, або Eitherмонади. Або написати видатні обчислення за допомогою Stateмонади. Але для того, хто не розуміє поняття монад, все це здається чимось чорним чаклунством.

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

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


2

Читання не має нічого спільного з парадигмами, моделями тощо. Чим більше код відображає семантику вашого проблемного домену, тим сильніше він оперує термінологією та ідіомами такого проблемного домену, тим він читає.

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

Хоча, існує багато інших семантик, які могли б бути ближчими до реального світу, ніж чистий функціонал, чистий OOP, чистий потік даних або чисте, що б коли-небудь було. І завдяки цьому факту, мовно-орієнтований підхід до вирішення проблем створює найбільш читабельний код, перемагаючи всі існуючі "чисті" парадигми. З мовами, що стосуються домену, кожна проблема виражається у власній природній термінології. А функціональні мови дещо краще, ніж основні засоби OOP у справі полегшення впровадження DSL (хоча, є набагато кращі підходи).


1

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

Висновок типу може бути хитрою рисою. Зазвичай це чудовий прискорювач розвитку, однак, іноді може бути важко розібратися, які типи залучені через відсутність контексту, що призводить до заплутаних помилок. Це не обмежується язиками функціонального програмування - я бачив це і в шаблонах C ++!

Сучасні мови мають тенденцію бути багатопарадигмою . Сюди входить і C #, і F #. Можна написати функціональний стиль у C # та імперативний стиль у F #. Ті ж люди, які критикують функціональні мови, ймовірно, пишуть функціональний код на своїй об'єктно-орієнтованій мові.

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

  1. Зміна стилю, коли ви вивчаєте мову (а не рефакторинг), що призводить до неузгодженості.
  2. Занадто багато в одному файлі.
  3. Забагато тверджень в одному рядку.

Щодо помилок я також додам: 4. Надмірне використання символів, наприклад: ~ @ # $% ^ & * () -_ + = \ | /.,; 5. Неявні функції: необов'язкові декларації / ключові слова / заяви, неявні перетворення тощо;
Сергій Соколенко
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.