Является ли Javascript функциональным языком программирования

34
  • Является ли Javascript функциональным языком? Я знаю, что у него есть объекты, и вы также можете делать с ним ООП, но это также функциональный язык, можно ли его использовать таким образом?
  • Вы знаете, как ООП стало / кажется следующей эволюцией в программировании, означает ли это, что «Функциональное программирование» - это следующая эволюция (Примечание: это НЕ подсказка для мнения, НО подсказка для ответа, основанного на фактических данных, и эта заметка больше для модераторов, чем для авторов;)).
  • Я лучше всего учусь на примерах, может быть, кто-то может показать выполнение той же задачи способом ООП, а затем способом функционального программирования, чтобы я мог понять и сравнить, что функциональное программирование делает / является.

Честно говоря, я не совсем понимаю «Функциональное программирование»: P Так что сравнение Javascript с функциональным программированием может быть совершенно неверным.

Чтобы выразить функциональное программирование в терминах непрофессионалов: является ли это просто преимуществом абстракции через использование анонимных функций?

Или это слишком просто? Проще говоря, ООП является преимуществом абстракции через объекты, но я считаю, что это слишком упрощенно для описания ООП.

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

Пример Javascript ООП:

// 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]);
Marek
источник
Это зависит от определения «функционального языка программирования». В широком смысле, его можно понимать как способность строить функциональные значения с закрытыми значениями, то есть как иметь «лямбда-конструкцию» (в смысле лямбда-исчисления), и тогда 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 функциональным языком? Я знаю, что у него есть объекты, и вы также можете делать с ним ООП, но это также функциональный язык, можно ли его использовать таким образом?

Иногда люди говорят функциональное программирование, когда они имеют в виду императивное программирование или процедурное программирование . Строго говоря, функциональное программирование - это:

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

Хотя Javascript не широко известен и не используется в качестве функционального языка, он имеет некоторые функциональные элементы :

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

Scheme - это диалект Lisp и, вероятно, один из языков, о которых думают большинство программистов, когда обсуждают функциональное программирование. Когда дело доходит до объектной ориентации , Javascript - это объектно-ориентированный язык. Но его объектная ориентация основана на прототипе :

Программирование на основе прототипов - это стиль объектно-ориентированного программирования, в котором отсутствуют классы, а повторное использование поведения (известное как наследование в языках на основе классов) выполняется посредством процесса клонирования существующих объектов, которые служат прототипами. Эту модель также можно назвать бесклассовым, ориентированным на прототип или программированием на основе экземпляров. Делегирование - это языковая функция, которая поддерживает программирование на основе прототипов.

Поэтому, хотя Javascript является объектно-ориентированным, он не следует более распространенной модели , основанной на классах , как это делают языки, такие как C ++, C #, Java и PHP (и многие другие). И, конечно, это также императивный язык, который приводит к путанице с функциональным программированием, которое я описал выше.

Вы знаете, как ООП стал / кажется следующей эволюцией в программировании, означает ли это, что «Функциональное программирование» - это следующая эволюция

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

Javascript, как я описал выше и, как и многие другие языки, является мультипарадигмой. Это позволяет вам писать код в императивном, основанном на прототипах объектно-ориентированном и функциональном стиле. Вам решать, какой из них лучше всего подходит для всего, что вы строите. Существует также несколько отдельных языков парадигмы, каноническим примером является Java, который допускает только объектно-ориентированное программирование на основе классов. 1 .

Вы должны действительно противостоять любому желанию относиться к языкам и парадигмам как к модным заявлениям. Существует множество дерьма, написанного в основном фанатами / фанатками или специалистами по маркетингу, с небольшим (если вообще) знанием и пониманием программирования. Такие термины, как «лучше», «более развитый» и т. Д., Просто не применяются.

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

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

1 Но в последнее время мы пытаемся расширить область его применения на общее программирование, давайте посмотрим, как это происходит.


В заключение:

  • Сконцентрируйтесь на изучении Javascript, это красивый и чрезвычайно полезный язык. Учи язык, а не ажиотаж.
  • Несколько разных парадигм, все одинаково полезны. Вам решать, какой из них вы предпочитаете, а какой подходит лучше всего, что вы строите.
  • Если вы хотите изучать функциональное программирование, выберите более подходящий язык, например Scheme или Clojure . Но сначала вам нужно понять математические концепции.
  • Сделайте некоторое исследование, прежде чем спросить. На большинство ваших вопросов отвечают соответствующие статьи Википедии. Умение исследовать и спрашивать - чрезвычайно важный навык для любого программиста.
Яннис
источник
5
+1 Отличный ответ. Из-за структуры обучения программированию новые программисты, похоже, считают парадигмы эксклюзивными и дискретными, но это не так. Попробуйте написать ООП-код, который использует функциональные концепции, когда это имеет смысл. Программирование на основе событий - это парадигма, но аспекты EDP, безусловно, влияют на каждый графический интерфейс и веб-программу. Полиморфизм , основная особенность ООП, является действительно общим программированием. Обозначение этих идей помогает нам осмыслить хорошее программирование, но вы не должны использовать одно, исключая другие.
Кодзиро
Хотя исходный вопрос и ваш ответ описывают Javascript и его отношение к функциональному программированию, я думаю, что ваш ответ является одним из лучших сравнений между ОО и функциональным программированием, которые я видел. Отлично сработано.
AnotherDeveloper
«Это был бы ужасный способ обучения». Я только что закончил читать эту книгу, которая представляет проблему и решает ее с помощью ряда парадигм, включая стили ООП и ФП: github.com/crista/exercises-in-programming-style . Я многому научился от этого!
Ник
@nick Это может только описать вам, как выглядит парадигма и как она работает, но она не говорит вам, почему , что, возможно, является наиболее важным аспектом. Но вам нужно узнать, как, прежде чем вы сможете узнать, почему :) иногда мы забываем, что эти вещи являются процессом.
Мэтью Брент
8

Javascript можно использовать как функциональный язык, на самом деле он делает это довольно хорошо. Можно реализовать монады с поддержкой лямбда-конструкции и т. Д. Это не только функциональный язык, поскольку он также имеет много объектно-ориентированных функций, но его можно использовать таким образом. На самом деле я считаю, что использование Javascript в качестве функционального языка - отличный способ его использования. (Пример jQuery и underscore.js)

Захари К
источник
хорошо и кратко! Согласились, что функциональное программирование часто является самым простым способом сделать что-то в js.
bunglestink
Еще интереснее, чем монады, вы можете реализовать стрелки это JS ( cs.umd.edu/projects/PL/arrowlets ). Что касается того, почему кому-то нужны стрелки в JavaScript, это открытый вопрос. Но это может быть сделано.
личность
Я признаю, что недостаточно разбираюсь в стрелках, чтобы знать, будут ли они полезны. Но я работаю над Книгой о монадах в Javascript и могу добавить главу о стрелах ( shop.oreilly.com/product/0636920023890.do )
Захари К,
6

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

Чтобы понять функциональный подход, вам нужно сначала получить базовую математику . Если вы хотите понять, что значит кодировать в функциональном стиле в Javascript, начните использовать jQuery .

SK-логика
источник
2

Нет.

JavaScript - это прежде всего объектно-ориентированный язык.

Это не означает, что вы не можете писать программы на JavaScript в функциональном стиле, так как вы можете принять функциональный стиль на любом полном языке Тьюринга, если будете стараться достаточно сильно. Вы можете заниматься функциональным программированием на ассемблере, если хотите. Но это не делает каждый язык функциональным. С таким же успехом вы можете назвать Haskell императивом или Java языком логического программирования - если вы воспользуетесь этим подходом, термины вскоре станут бессмысленными.

ИМО способ классифицировать язык в соответствующую парадигму состоит в том, чтобы рассмотреть:

  • Что является доминирующим стилем, допускаемым языковыми конструкциями (очевидно, ООП для JavaScript, функциональные языки вместо этого подчеркивают функции и неизменные значения данных)
  • Какая парадигма поддерживается в основных библиотеках языка (опять же, ООП для JavaScript)
  • Какие функции отключены или не приветствуются в языке (функциональные языки не допускают или запрещают изменяемые переменные, что не относится к JavaScript)
  • Какой стиль разработки распространен в сообществе разработчиков, использующих язык (опять же, ООП явно преобладает в мире JavaScript)

Лично я нахожу довольно забавным, что многим людям нравится утверждать, что язык является "функциональным" только потому, что это модный термин в настоящее время :-)

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

mikera
источник
What is the dominant style enabled by the language constructsСмею вас попробовать применить это к Perl ... Или к любому другому из ваших
замечаний
2
Perl? Хороший вызов! Это в некотором роде ассемблерный язык в том смысле, что вы можете взломать практически любую парадигму, которую вы хотите вместе, но в обычном использовании, которое я видел (скриптинг), он используется в основном как императивный / процедурный язык.
Микера
Ну, ой тоже довольно распространено. Конечно, конечно. И, функционально тоже , хотя необычно. Perl - это просто 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 некоторые из них прямо установлены.

Важно помнить (ИМО), что в то время как 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 из превосходного "Eloquent Javascript"

Маленький интриган

мой друг написал библиотеку JS на основе Little Schemer

Хороший учебник по схеме, который может помочь вам лучше понять FP

sunwukung
источник