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


12

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

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

Моє запитання: скажіть, проблема зараз полягає в тому, щоб увійти до верблюда,

такий, що qwe_asd_zxc_rty_fgh_vbnстаєqweAsdZxcRtyFghVbn

Процедурний спосіб:

  1. розділіть його уздовж _
  2. Проведіть цикл через масив, пропускаючи перший елемент
  3. за кожен запис ми пишемо великі літери першої літери
  4. об'єднайте результати разом

Функціональний спосіб:

  1. якщо не вдається знайти _поверненняinput
  2. вирізати inputуздовж першого _(таким, що ми отримаємо qweі asd_zxc_rty_gfh_cvb)
  3. з великої літери headнапишіть і сформулюйте, що сf(tail)

Гаразд, якщо у вас є функціональний фон І у вас є великий досвід процесуально-програмового програмування, я хотів би запитати: чи знадобиться вам більше часу, щоб розібратися в процедурному способі, або знадобиться більше часу, щоб ви з'ясували функціональний шлях?

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


5
Ерм, "процедурний спосіб" здається мені абсолютно функціональним, якщо ми використовуємо mapдля кроку 3 замість мутації циклу. Другий підхід - це те, що я б врахував лише в тому випадку, якщо в стандартній бібліотеці немає розбитої функції (у такому випадку її слід порівнювати з необхідним рішенням, яке також не використовується split).
sepp2k

8
Ні в одному з ваших прикладів немає нічого конкретно функціонального чи процедурного. Мені це здається, ніби ви намагаєтесь екстраполювати з-за неправильного розуміння функціональних програм. Недарма ви отримуєте незвичайні результати.
Рейн Генріхс

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

1
Я думаю, що відмінність між функціональними та процедурними стає суперечливою, оскільки мови мови, такі як JavaScript, C #, Groovy, містять все більш функціональні функції.
користувач281377

2
Імперативне програмування набагато складніше та протиінтуїтивне для тих, хто не мав попереднього досвіду програмування. Вираз на кшталт x=x+1може підірвати несподіваний мозок. Функціональне програмування є природним, це не що інше, як чисті та суто суворо математичні функції.
SK-логіка

Відповіді:


12

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

Новачкам часто досить інтуїтивно зрозуміти, що ви не можете просто змінити значення чогось.

Там, де я вивчав КС, нас вивчали функціональну мову як наш перший курс. І всі, хто раніше вивчив C ++ або Java, боролися з цим. Ті, хто був новаком у програмуванні, підібрали його досить легко.


jalf Ви один із тих, хто програмує, і досить легко його взяв?
Pacerier

Я був десь посеред. Я до цього часу трохи поцупив C ++ і деяким PHP, але цього недостатньо, щоб реально звикнути до імперативного мислення. Шаблон був досить чітким, коли ти дивився на клас в цілому. Крім того, це було майже десять років тому, так що ні, я не зовсім новачок у програмуванні сьогодні;)
jalf

Змінні змінні? Хіба математика не є функціональною мовою програмування? змінні математики, безумовно, змінюються, ні?
користувач56834

20

Це просто різне

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

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

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

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


4

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

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

Щоб отримати кращий приклад функціонального програмування, розгляньте більш загальну проблему: замість "пошуку підкреслення та перетворення наступної літери у великі регістри", розгляньте це як лише один особливий випадок пошуку шаблону та виконання якогось довільного коду, коли це знайдено.

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

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

Результат полягає в тому, що ми можемо порівняно легко узагальнити проблему вище. Замість жорсткого кодування '_' та 'верхнього регістру' безпосередньо в трансформацію, однак, ми можемо мати щось на кшталт:

s&r(pattern, transform, string) {
    if (!pattern(string))
        return string
    else
        return transform(matched part of string) + s&r(rest of string);
}

Але, на відміну від чогось, де ми задаємо шаблон як РЕ, ми можемо вказати шаблон безпосередньо як реальну функцію та все ж використовувати її, щось на зразок:

my_pattern(string) return beginning(string) == '_';

І тоді ми передаємо цю функцію s & r. Зараз це досить тривіальна функція, і ми закодували її повністю статично. Функціональна мова значною мірою стає цікавою, коли ми її використовуємо так, як ми можемо переглядати, і генерувати абсолютно нову функцію на льоту, базуючись на щось на зразок введення користувача, але на відміну від RE, для запуску цієї функції не потрібен спеціальний інтерпретатор RE - це просто нормальна функція, як і будь-яка інша.


4

Ось повний код у Ракетці :

;; camelize : string -> string
(define (camelize str)
  (let ([parts (regexp-split #rx"_" str)])
    ;; result of regexp-split is never empty
    (apply string-append
           (first parts)
           (map string-titlecase (rest parts)))))

(camelize "qwe_asd_zxc_rty_fgh_vbn")
;; => "qweAsdZxcRtyFghVbn"

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

До речі, приклад очікуваного результату в початковій публікації невірний: у ньому пропущено "h" наприкінці.


gd для вказівки на це. відредаговано
Pacerier

3

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

Тепер процедурна модель дещо наближається до звичної машинної архітектури: завдання - це пам'ять (або реєстрація). Виклики процедур - це справді просто фантазійні стрибки, а ifце насправді умовний стрибок тощо. Але, наприклад, у Ліспі немає простого низького рівня, еквівалентного лексичній зв'язці чи лямбда-виразу. Розуміння цього вимагає від вас уявити цілком окрему абстрактну функціональну машину між рівнем мови та фізичною машиною, тому що, мабуть, більшість людей ніколи так не дістається.

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


7
За цією логікою Ассемблер повинен бути найпростішим з усіх мов для вивчення :)
Хомде

4
Функціональне програмування зрозуміти досить просто, якщо ви підійшли до нього з правильного напрямку. «Абстрактна функціональна машина», яку ви згадуєте, - це просто алгебра . Оцінювання проводиться шляхом переписування терміна; Застосування функції здійснюється за допомогою підстановки. Програмісти вчаться вирішувати проблеми за допомогою тих же інструментів, які ви бачили за роки математичних статей. Якщо вони переслідують КС, є час, щоб пізніше зустріти стоп черепах; якщо ні, вони все ще засвоїли корисні навички вирішення проблем та принципи дизайну. Погляньте на те, як проектувати програми .
Райан Калпеппер

2
@mko Ні, за цією логікою фактичні байт-коди 011011001001101...були б найлегшою мовою для вивчення!
MarkJ

2
@konrad: Асемблер RISC - це, мабуть, найпростіша мова для вивчення. Знати, як змусити це зробити щось корисне - це інша історія разом ...
Брайан Боттчер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.