サーチ…


備考

機能プログラミングとは何ですか?
Functional ProgrammingまたはFPは、2つの主な概念である不変性ステートレス 性に基づいて構築されたプログラミングパラダイムです.FPの背後にある目標は、コードを読みやすく、再利用可能で、移植性の高いものにすることです。

機能的なJavaScriptとは
JavaScriptを関数型言語と呼ぶかどうかを議論してきました。しかし、JavaScriptの性質上、JavaScriptを機能として絶対に使用することはできます。

例は各概念を詳細にカバーするべきであり、ここで提供されているリンクは参考のためのものであり、一度概念を説明すると削除する必要があります。

引数としての関数の受け入れ

function transform(fn, arr) {
    let result = [];
    for (let el of arr) {
        result.push(fn(el)); // We push the result of the transformed item to result
    }
    return result;
}

console.log(transform(x => x * 2, [1,2,3,4])); // [2, 4, 6, 8]

ご覧のとおり、 transform関数は関数とコレクションという2つのパラメータを受け入れます。次に、コレクションを反復し、結果に値をプッシュし、それぞれにfnを呼び出します。

見慣れた?これはArray.prototype.map()がどのようにArray.prototype.map()するかと非常によく似ています!

console.log([1, 2, 3, 4].map(x => x * 2)); // [2, 4, 6, 8]

高次関数

一般に、他の関数を引数として取るか、(またはその両方を)返すことによって、他の関数を操作する関数は高次関数と呼ばれます。

高次関数は、別の関数を引数として取る関数です。コールバックを渡すときに高次関数を使用しています。

function iAmCallbackFunction() {
    console.log("callback has been invoked");
}

function iAmJustFunction(callbackFn) {
    // do some stuff ...

    // invoke the callback function.
    callbackFn();
}

// invoke your higher-order function with a callback function.
iAmJustFunction(iAmCallbackFunction);

高次関数は、結果として別の関数を返す関数でもあります。

function iAmJustFunction() {
    // do some stuff ...

    // return a function.
    return function iAmReturnedFunction() {
        console.log("returned function has been invoked");
    }
}

// invoke your higher-order function and its returned function.
iAmJustFunction()();

アイデンティティモナド

これは、JavaScriptでアイデンティティモナドの実装の例であり、他のモナドを作成するための出発点として役立つ可能性があります。

Douglas Crockfordによるモナドと生殖腺の会議

このモナドが提供する柔軟性と複雑な悪夢のため、関数を再利用するこのアプローチを使用すると簡単になります。

f(g(h(i(j(k(value), j1), i2), h1, h2), g1, g2), f1, f2)

読みやすく、素敵できれいな:

identityMonad(value)
    .bind(k)
    .bind(j, j1, j2)
    .bind(i, i2)
    .bind(h, h1, h2)
    .bind(g, g1, g2)
    .bind(f, f1, f2);

function identityMonad(value) {
    var monad = Object.create(null);
    
    // func should return a monad
    monad.bind = function (func, ...args) {
        return func(value, ...args);
    };

    // whatever func does, we get our monad back
    monad.call = function (func, ...args) {
        func(value, ...args);

        return identityMonad(value);
    };
    
    // func doesn't have to know anything about monads
    monad.apply = function (func, ...args) {
        return identityMonad(func(value, ...args));
    };

    // Get the value wrapped in this monad
    monad.value = function () {
        return value;
    };
    
    return monad;
};

プリミティブ値で動作します

var value = 'foo',
    f = x => x + ' changed',
    g = x => x + ' again';

identityMonad(value)
    .apply(f)
    .apply(g)
    .bind(alert); // Alerts 'foo changed again'

また、オブジェクト

var value = { foo: 'foo' },
    f = x => identityMonad(Object.assign(x, { foo: 'bar' })),
    g = x => Object.assign(x, { bar: 'foo' }),
    h = x => console.log('foo: ' + x.foo + ', bar: ' + x.bar);

identityMonad(value)
    .bind(f)
    .apply(g)
    .bind(h); // Logs 'foo: bar, bar: foo'

すべてを試してみましょう:

var add = (x, ...args) => x + args.reduce((r, n) => r + n, 0),
    multiply = (x, ...args) => x * args.reduce((r, n) => r * n, 1),
    divideMonad = (x, ...args) => identityMonad(x / multiply(...args)),
    log = x => console.log(x),
    substract = (x, ...args) => x - add(...args);

identityMonad(100)
    .apply(add, 10, 29, 13)
    .apply(multiply, 2)
    .bind(divideMonad, 2)
    .apply(substract, 67, 34)
    .apply(multiply, 1239)
    .bind(divideMonad, 20, 54, 2)
    .apply(Math.round)
    .call(log); // Logs 29

純粋な関数

関数型プログラミングの基本原則は、アプリケーションの状態(ステートレス性)とその範囲外の変数(不変性)の変更を避けることです。

純粋な関数は次のような関数です。

  • 与えられた入力で常に同じ出力を返す
  • 彼らは範囲外の変数に依存しません
  • 彼らはアプリケーションの状態を変更しません( 副作用なし

いくつかの例を見てみましょう:


純粋な関数はスコープ外の変数を変更してはならない

不純な関数

let obj = { a: 0 }

const impure = (input) => {
  // Modifies input.a
  input.a = input.a + 1;
  return input.a;
}

let b = impure(obj)
console.log(obj) // Logs { "a": 1 }
console.log(b) // Logs 1

この関数は、スコープの外にあるobj.a値を変更しました。

純粋な関数

let obj = { a: 0 }

const pure = (input) => {
  // Does not modify obj
  let output = input.a + 1;
  return output;
}

let b = pure(obj)
console.log(obj) // Logs { "a": 0 }
console.log(b) // Logs 1

この関数はオブジェクトのobj値を変更しませんでした


純粋な関数は、スコープ外の変数に依存してはならない

不純な関数

let a = 1;

let impure = (input) => {
  // Multiply with variable outside function scope
  let output = input * a;
  return output;
}

console.log(impure(2)) // Logs 2
a++; // a becomes equal to 2
console.log(impure(2)) // Logs 4

この不純な関数はaそのスコープの外で定義された変数a依存しています。したがって、aが変更された場合、 impure関数の結果は異なります。

純粋な関数

let pure = (input) => {
  let a = 1;
  // Multiply with variable inside function scope
  let output = input * a;
  return output;
}

console.log(pure(2)) // Logs 2

pure関数の結果は、スコープ外の変数に依存ません



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow