Подтвердить что ты не робот

Как выкладывается функциональное приложение JavaScript на основе программирования?

Я работал с node.js некоторое время в приложении чата (я знаю, очень оригинально, но я понял это был бы хороший учебный проект). Underscore.js предоставляет множество концепций функционального программирования, которые выглядят интересными, поэтому я хотел бы понять, как будет настраиваться функциональная программа в JavaScript.

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

var external;
function foo() {
   external = 'bar';
}
foo();

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

Хорошо, так как это работает, когда вы имеете дело с объектами, а что нет? Например, много раз у меня будет конструктор и метод init, который инициализирует объект, например:

var Foo = function(initVars) {
   this.init(initVars);
}

Foo.prototype.init = function(initVars) {
   this.bar1 = initVars['bar1'];
   this.bar2 = initVars['bar2'];
   //....
}

var myFoo = new Foo({'bar1': '1', 'bar2': '2'});

Итак, мой метод init преднамеренно вызывает побочные эффекты, но что будет функциональным способом справиться с такой же ситуацией?

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

4b9b3361

Ответ 1

Вы должны прочитать этот вопрос:

Javascript как функциональный язык

Есть много полезных ссылок, в том числе:

Теперь, по моему мнению. Многие люди неправильно понимают JavaScript, возможно потому, что его синтаксис похож на большинство других языков программирования (где Lisp/Haskell/OCaml выглядят совершенно иначе), JavaScript не является объектно-ориентированным, это фактически язык прототипа. У него нет классов или классического наследования, поэтому его нельзя сравнивать с Java или С++.

JavaScript может быть лучше по сравнению с Lisp; он имеет замыкания и первоклассные функции. Используя их, вы можете создавать другие методы функционального программирования, такие как частичное приложение (currying).

Возьмем пример (используя sys.puts из node.js):

var external;
function foo() {
    external = Math.random() * 1000;
}
foo();

sys.puts(external);

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

(function() {
    var external;
    function foo() {
        external = Math.random() * 1000;
    }
    foo();

    sys.puts(external);
})();

Обратите внимание: мы не можем ничего делать с external или foo вне области видимости. Они полностью завернуты в свое закрытие, неприкасаемые.

Теперь, чтобы избавиться от побочного эффекта external:

(function() {
    function foo() {
        return Math.random() * 1000;
    }

    sys.puts(foo());
})();

В конце концов, пример не является чисто функциональным, потому что он не может. Использование случайного числа читается из глобального состояния (для получения семени), и печать на консоль является побочным эффектом.

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

var Square = function(x, y, w, h) {
   this.x = x;
   this.y = y;
   this.w = w;
   this.h = h;
};

function getArea(square) {
    return square.w * square.h;
}

function sum(values) {
    var total = 0;

    values.forEach(function(value) {
        total += value;
    });

    return total;
}

sys.puts(sum([new Square(0, 0, 10, 10), new Square(5, 2, 30, 50), new Square(100, 40, 20, 19)].map(function(square) {
    return getArea(square);
})));

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

Реальный трюк с использованием объектов в функциональном стиле заключается в том, чтобы убедиться, что вы не полагаетесь на их побочные эффекты, но вместо этого считаете их неизменными. Легкий способ - всякий раз, когда вы хотите изменить свойство, просто создайте новый объект с новыми деталями и вместо этого передайте его (это подход, который часто используется в Clojure и Haskell).

Я твердо верю, что функциональные аспекты могут быть очень полезны в JavaScript, но в конечном итоге вы должны использовать все, что делает код более читаемым и что работает для вас.

Ответ 2

Вы должны понимать, что функциональное программирование и объектно-ориентированное программирование несколько противоречат друг другу. Невозможно, чтобы оба были чисто функциональными и чисто объектно-ориентированными.

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

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

Если вы хотите быть более прагматичным в этом отношении, есть некоторые вдохновения из чисто функционального мира, который вы могли бы использовать.

Я стараюсь придерживаться следующих правил:

Функции, выполняющие вычисления, не должны изменять состояние. И функции, которые изменяют состояние, не должны выполнять вычисления. Кроме того, функции, которые изменяют состояние, должны изменяться как можно меньше состояний. Цель состоит в том, чтобы иметь множество маленьких функций, которые делают только одно. Затем, если вам нужно сделать что-нибудь большое, вы создаете кучу небольших функций, чтобы делать то, что вам нужно.

Из следующих правил можно извлечь ряд преимуществ:

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

  • Надежность кода. Легче рассуждать о правильности кода, если он менее сложный.

  • Легче тестировать функции, когда они делают только одно. Таким образом, для тестирования требуется меньше особых случаев.

Update:

Встроенное предложение из комментария.

Обновление 2:

Добавлены полезные ссылки.

Ответ 3

Я думаю, http://documentcloud.github.com/underscore/ должно быть хорошо подходить под то, что вам нужно - он обеспечивает наиболее важные функции более высокого порядка для функционального программирования и не имеет клиентских функций для манипуляций с DOM, которые вам не нужны на стороне сервера. Хотя у меня нет опыта с этим.

В качестве побочного примечания: основной функцией функционального программирования IMHO является Ссылочная прозрачность результата функции - функция зависит только от ее параметров - функции не зависит от изменений на других объектах и ​​не вносит никаких изменений, кроме значения результата. Это позволяет легко рассуждать о правильности программы и очень ценно для реализации предсказуемой многопоточности (если это необходимо). Хотя JavaScript не является языком ставок для FP - я ожидаю, что неизменяемые структуры данных будут очень дорогими, чтобы использовать их.

Ответ 4

Итак, нужно отметить 2 вещи,

  • В вашем первом примере ваша переменная не будет протекать в глобальную область и как она должна быть выполнена, старайтесь никогда не использовать переменные без объявления их, т.е. test = 'data' приведет к утечке данных в глобальной области.

  • Второй пример также правильный, bar1 и bar2 будут объявлены только на объекте Foo.

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

Если вы ищете инфраструктуру разработки приложений, посмотрите ExtJs. Лично я думаю, что это прекрасно впишется в модель, против которой вы пытаетесь развиваться. Просто имейте в виду, как работает их модель лицензирования, прежде чем вкладывать в нее значительные средства.