2017-02-10 4 views
1

いくつかの機能を作ってみたいです。 f3(x)f1(f2(x)) と同じものでなければならない場合f3(x,y)が、その後f1(x, f2(y)) と同じものでなければならない場合f3 = _.flowRight(f1,f2);その後、Lodashの流れを使って多様なアリティの関数を構成する方法は?

...:私はすでにこのことを知っていますか?

(ユースケースは、Node.jsの/特急ミドルウェア機能の組成物である。)

+0

私はlodashの流れについての昨日の答えを書いた。私はいくつかの関数が作成されることを意図していないので、非常に役に立ちますと思っています:http://stackoverflow.com/a/42139851/633183 – naomik

+0

1時間前に別の解答を既存のコードベースに書きました。私はそれがthsiトピックに関連していると思うと思う:http://stackoverflow.com/a/42164779/633183 – naomik

+0

あなたの "問題"はあなたが様々な* arity *の機能を構成しようとしていることです。バイナリ関数を持つ単項関数。関数の構成は、単項関数を排他的に使用する場合に最適です。簡単な答えは 'const f3 =(x、y)=> f1(x、f2(y))'です。 – naomik

答えて

2

あなたはlodash相当を持っていない可能性が非常に具体的な要件を持っているようですね。

これはあなた自身のヘルパー機能を書くのはなぜでしょうか?

function composeFuncs(f1, f2) { 
 
    return function(x, y) { 
 
    return f1.call(this, x, f2.call(this, y)); 
 
    }; 
 
} 
 

 
var myObj = { 
 
    add: function(val1, val2) { 
 
    return this.myVal + val1 + val2 
 
    }, 
 
    mult: function(val) { 
 
    return this.myVal * val 
 
    }, 
 
    myVal: 7 
 
}; 
 

 
myObj.newFunc = composeFuncs(myObj.add, myObj.mult); 
 

 
// 7 + 1 + 7 * 2 = 22 
 
console.log(myObj.newFunc(1, 2));

編集:_.flowRightが行うthis同じように処理するために更新しました。

+0

もちろん、私はこれを行うことができましたが、おそらくlodashから_.flowRightとして 'this'の扱いをしなければならないでしょう。関数型プログラミングではかなり新しいことがあるので、私は必要なもののようなもののためのよく知られたパターンがあると思った。 :) – matths

+0

@matths 'this'伝播を含むように変更されました。これを使用したい場所の例を教えてください。私はこれによく知られているパターンに慣れていませんが、あるかもしれません。 – JLRishe

+0

私は現在エクスプレス/ミドルウェアのような接続機能を書いています。一つは 'method(m、handler)'です。ここでmはget、post、putなどで、もう一つは 'path(p、handler)'です。合成は 'method(m、path(p、handler))'を実行する 'request(m、p、handler)'でなければなりません。各ミドルウェアの戻り値は、単独でハンドラ関数です。私は確信が持てません、私は十分に説明することができます。 – matths

4

次の画像では、値のプレースホルダとして{_}を使用します。我々は何かを渡すコードでと考えてください。

[OK]をはさんがあなたの関数がしなければならないだろうか想像してみましょう...

a bad dream

  • いこれはそう一般的な変換のように?つまり、これを多くの場所で使用できると思いますか? –関数型プログラミングは、再利用性が高く、さまざまな方法で組み合わせることができるビルド機能を促進します。 f1f2の違いは何ですか? f1は1つの引数だけを取得する単項関数です。f2は2つの関数を取得するバイナリ関数です。どの人がどの場所に行くのかを覚えていますか?
  • f1(x)が配置される位置を支配するものはf2ですか?
    • f2(f1(x),y)
    • からf2(y,f1(x)) ...
    • が他よりも有用なものの一つである比較しますか?
    • あなたはf1の位置が覚えていますか?あなたが好きな構図を機能

リコールなど、多くの機能を一緒に連鎖することができるはずです。 someFuncの無駄を理解するのを助けるために、3つの関数と3つの引数を受け入れることを想像してみましょう。ここでも、パターンは

a nigthmare

  • ありますか?たぶん、f2f3それぞれが2
  • を取得しながら、しかし、あなたはまだ、一つだけ引数を取得厄介な単項機能f1を持っていることはf2f3は前の関数の値が常に右側に呼び出す必要が行っていることは事実です
    • は左チェーンへf3(z,f2(y,f1(x)))
    • f3(f2(y,f1(x)),z)にたぶんf3ニーズが、右からf2チェーンの比較しますか?
    • 私は魔法のようにあなたはすでにあなたの組成のバイナリの機能を持つ単項混合まし
  • 同じ場所に連鎖した引数を必要とするバイナリの機能のあなたの全体のAPIを想像することはできません。なぜそれらをそのタイプの関数だけに恣意的に制限するのですか? 3つ以上の引数の関数はどうでしょうか?

答えは、自己実現

機能組成物はここに誤用されています。関数の構成は、単項関数を排他的に(それぞれ1つの引数を受け入れる関数)構成している場合にのみ機能します。直ちに分解され、高いアリティの関数で混合するときには一般化できません。

f3が名前を必要とし、f1,f2の2つのパラメータの組み合わせである場合、コードは…それは非常に多くの任意の選択を行いますので

const f3 = (x,y) => f1(x, f2(y)) 

、それは、任意の有用な方法で一般化することはできません。それはそのままにしましょう。


「だから、様々なアリティの機能を構成する方法はありますか?」

確かに、さまざまな実用性の技術があります。私はああ、ところで、私たちは単一のコード行でLodashのflowRight(複雑なflowのラッパー)を置き換え

const partial = (f,...xs) => (...ys) => f(...xs, ...ys) 
 

 
const add = (x,y) => x + y 
 

 
const mult = (x,y) => x * y 
 

 
const sq = x => mult (x,x) 
 

 
// R.I.P. lodash.flowRight 
 
const compose = ([f,...fs]) => x => 
 
    f === undefined ? x : f (compose (fs) (x)) 
 
        
 
let f = compose([partial(add, 1), sq, partial(mult, 3)]) 
 

 
console.log(f(2)) 
 
// add(1, square(mult(3, 2))) 
 
// add(1, square(6)) 
 
// add(1, 36) 
 
// => 37

ここで実用性の高いpartial機能の使用方法を示します。

関連する問題