Чи є JavaScript функціональною мовою програмування


34
  • Чи функціональна мова Javascript? Я знаю, що у неї є об'єкти, і ви також можете робити OOP з нею, але це також функціональна мова, чи можна її використовувати таким чином?
  • Ви знаєте, як OOP став / здається, що наступна еволюція в програмуванні, чи означає це, що "Функціональне програмування" - це наступна еволюція (Примітка: це НЕ підказка для думки, АЛЕ запрошення на відповідь, заснований на фактичних доказах, і ця примітка більше для модераторів, ніж учасників;)).
  • Я найкраще навчаюсь на прикладах, можливо, хтось може показати те, що виконує одне і те ж завдання в рамках OOP, а потім функціональним способом програмування, щоб я зрозумів і порівняв, що робить / є функціональне програмування.

Я не дуже розумію «Функціональне програмування», якщо чесно: P Порівнювати Javascript з функціональним програмуванням може бути абсолютно неправильним.

Поставити функціональне програмування в лайманських термінах: чи просто вигода абстракції КРАЙ за допомогою анонімних функцій?

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

Це хороший приклад функціонального програмування? ...

Приклад Javascript OOP:

// sum some numbers
function Number( v )
{ 
  this.val = v;
}

Number.prototype.add( /*Number*/ n2 )
{
    this.val += n2.val;
}

Приклад функціонального програмування:

function forEach(array, action) 
{
   for (var i = 0; i < array.length; i++)
       action(array[i]);
}  

function add(array)
{
    var i=0;
    forEach(array, function(n)
    {
        i += n;
    });
    return i;
}

var res = add([1,9]);

Це залежить від визначення "функціональної мови програмування". У широкому сенсі це можна розуміти як здатність будувати функціональні значення із закритими значеннями, тобто як конструкція "лямбда" (у значенні лямбда-числення), а потім Javascript підходить до рахунку.
Базиль Старинкевич

2
Or is that way too simple?Так, так і є. Анонімні функції іноді асоціюються з функціональними мовами та мовами декількох парадигм, які надають перевагу функціональному програмуванню, але вони не є унікальною характеристикою функціональних мов. Але якщо ви бачите їх як реалізацію λ-числення, то вони є основною частиною функціонального програмування, головне - що це не так просто :)
yannis

Дизайн Javascript запобігає реалізації можливостей оптимізації хвостових викликів. У моїх книгах одна лише перешкоджає позначати його функціональним.
dan_waterworth

I know it has objects & you can do OOP with it alsoНі, ти не можеш. Це програмування на основі прототипу, яке виключає відмінність між класом і об'єктом. Особисто я вважаю програмування на основі прототипу недоліком на цьому базовому рівні.
RokL

Javascript - це не функціональна мова, але впевнений, що він має функціональні особливості, але це добре старий імператив C, адже кожна мова має основні функціональні функції. Чиста функціональна мова, така як Haskell, ML та ін., - це декларативна, а не імперативна мова.
ALXGTV

Відповіді:


72

Чи функціональна мова Javascript? Я знаю, що у неї є об'єкти, і ви також можете робити OOP з нею, але це також функціональна мова, чи можна її використовувати таким чином?

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

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

Хоча Javascript не відомий і не використовується як функціональна мова, він має деякі функціональні елементи :

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

Схема - це діалект Ліспа , і, мабуть, одна з мов, про яку думають більшість програмістів, коли вони обговорюють функціональне програмування. Що стосується орієнтації на об'єкт , Javascript - це об'єктно-орієнтована мова. Але його об'єктна орієнтація заснована на прототипі :

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

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

Ви знаєте, як OOP став / здається, що наступна еволюція в програмуванні, чи означає це, що «Функціональне програмування» - це наступна еволюція

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

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

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

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

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

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


На закінчення:

  • Концентруйтесь на вивченні Javascript, це прекрасна і надзвичайно корисна мова. Вивчіть мову, а не ажіотаж.
  • Досить кілька різних парадигм, всі однаково корисні. Ви самі вирішуєте, який саме вам надаватимете перевагу, а який - найкраще, що б ви не будували.
  • Якщо ви хочете вивчити функціональне програмування, виберіть більш підходящу мову, як-от Схема або Clojure . Але спочатку потрібно розібратися в математичних поняттях.
  • Проведіть кілька досліджень, перш ніж запитати. На більшість ваших запитань відповідають відповідні статті у Вікіпедії. Знання, як досліджувати і як задавати, - надзвичайно важливий навик для будь-якого програміста.

5
+1 Відмінна відповідь. Через те, як структурується навчання програмуванню, нові кодери, здається, вважають парадигми винятковими та дискретними, але вони не є. Спробуйте написати OOP-код, який використовує переваги функціональних понять, коли це має сенс. Програмування на основі подій є парадигмою, але аспекти EDP впливають, безумовно, на кожну програму та веб-програму. Поліморфізм - основна особливість ООП - це справді загальне програмування. Названня цих ідей допомагає нам концептуалізувати гарне програмування, але ви не повинні використовувати одну для виключення інших.
kojiro

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

"Це був би жахливий спосіб вчитися". Я щойно закінчив читати цю книгу, яка представляє проблему, і вирішує її за допомогою ряду парадигм, включаючи стилі OOP та FP: github.com/crista/exercises-in-programming-style . Я багато чого навчився з цього!
Нік

@nick Це може лише описати вам, як виглядає парадигма та як вона працює, але вона не каже вам, чому , що, певно, є найважливішим аспектом. Але вам потрібно дізнатися, як перш ніж дізнатися чому :) Іноді ми забуваємо, що ці речі - це процес.
Метью Брент

8

Javascript можна використовувати як функціональну мову, адже він робить це досить добре. Можна реалізувати монади , які підтримують лямбда-конструкцію тощо. Це не виключно функціональна мова, оскільки вона також має багато об'єктно-орієнтованих функцій, але може бути використана таким чином. Насправді я вважаю, що використання Javascript як функціональної мови - це чудовий спосіб його використання. (Приклад jQuery та underscore.js)


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

Ще цікавіше, ніж монади, ви можете реалізувати стрілки JS ( cs.umd.edu/projects/PL/arrowlets ). Тепер, як і чому хтось - то хоче стрілки в JavaScript, це відкрите питання. Але це можна зробити.
rtperson

Я визнаю, що я недостатньо розумію стрілки, щоб знати, чи будуть вони корисні. Але я працюю над «Книгою про монади у Javascript» і можу додати розділ про стрілки ( shop.oreilly.com/product/0636920023890.do )
Zachary K

6

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

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


2

Ні.

JavaScript - це насамперед об'єктно-орієнтована мова.

Це не означає, що ви не можете писати програми JavaScript у функціональному стилі, оскільки ви можете прийняти функціональний стиль на будь-якій мові Тюрінга, якщо ви постараєтесь досить. Ви можете займатися функціональним програмуванням в асемблері, якщо хочете. Але це не робить кожну мову функціональною. Ви можете так само називати Haskell імперативом або Java логічною мовою програмування - якби ви скористалися таким підходом, умови незабаром стали б безглуздими.

ІМО спосіб класифікувати мову у відповідній парадигмі - це розглянути:

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

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

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


What is the dominant style enabled by the language constructsСмію ви спробувати застосувати це до Perl ... Або будь-який інший із ваших пунктів, дійсно :)
yannis

2
Perl? Гарний виклик! Це дещо схожа мова на монтажі в тому сенсі, що ви можете зламати майже будь-яку парадигму, яку хочете разом, але в загальному використанні, яке я бачив (написання сценаріїв), воно використовується в основному як імперативна / процедурна мова.
mikera

Що ж, ооп теж досить поширений. Зрозумілим чином. І, також функціональний , хоча і рідкість. perl - просто перл, немає сенсу намагатися розібратися з цим :)
yannis

JavaScript трохи функціональніший, ніж Java, оскільки він принаймні має функції закриття та функції першого класу. Але ваше право, JavaScript настільки ж функціональний, як і C #.
Райнос

2

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

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

Ще одна примітна ідіосинкразія функціонального стилю полягає в тому, що функції повинні ТІЛЬКИ повертати результат своєї оцінки та не мати побічних ефектів на стан поза сферою їх дії:

// oops, this is producing a side effect
function sideEffecter(){//theres no input...        
    window.thingy = 'foo';
    // hey, this isn't returning anything!!!
} 

Функціональні мови не руйнуються - це означає, що вони не мутують вхід, а повертають абсолютно нові дані на основі введених даних. Дивіться цю тему: https://stackoverflow.com/questions/749084/jquery-map-vs-each

Функціональні мови також містять багато спільних методів - з такими іменами, як "карта", "скласти", "зменшити", які обробляють списки / колекції. У JS, на відміну від інших мов, ми мусимо перетворити їх на існування - дивіться бібліотеки на зразок underscore.js для деяких прикладів, хоча остання реалізація JS містить деякі з них прямо.

Важливо пам’ятати (IMO), що, хоча JS може використовувати деякі функціональні структури, він не завжди добре підходить для виконання.

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

var test = ['foo', 'bar', 'baz'], removeFunc, removeLoop;

//(semi)functional style...
// to be really functional each condition in the ternary would be another function
removeFunc = function(src, trg) {
    return src.length === 0 ? 
        src : 
            src[0] === trg ? 
                src.slice(1) : 
                    [src[0]].concat(removeFunc(src.slice(1), trg));
};

//but this is faster
removeLoop = function(src, trg){
    var len = src.length, // using variables to represent state...
        i=0, 
        result = [];        
    while(i < n){
       if(src[i] !== trg){
          result.push(src[i]);
       }
       i = i+1;
    }
}

Крім того, якщо ви використовуєте функціональну конструкцію для удару циклів значного розміру і не використовуєте певну форму спеціального керування стеком, ви можете залити стек (хоча, справедливо кажучи, вам потрібен ВЕЛИКИЙ список, щоб це відбулося. ..). Ви також повинні взяти до уваги поєднання оптимізацій варіантів у кожному браузері, хоча, якщо ви працюєте в середовищі Node.js, це, очевидно, більше фіксованої цілі.

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

Ось декілька посилань, які можуть вас зацікавити:

Хороший розділ про функціональне програмування в JavaScript від чудового "Красномовного JavaScript"

Маленький Схемер

мій друг написав бібліотеку JS, засновану на Маленькому схемі

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

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