JavaScriptのpipe()およびcompose()の簡単な紹介

関数型プログラミングは、私にとって目を見張るような旅でした。この投稿とそれに似た投稿は、新しい関数型プログラミングの世界を旅する際に私の洞察と展望を共有する試みです。

Ramdaは、JavaScriptで関数型プログラミングを非常に簡単に行えるため、私の頼れるFPライブラリです。強くお勧めします。

ブロックを構成して構造を形成します。かなり深いもの…

パイプ

パイプの概念は単純です—それはn個の機能を組み合わせます。左から右に流れるパイプで、最後の関数の出力で各関数を呼び出します。

誰かの名前を返す関数を書きましょう。

getName =(person)=> person.name
getName({name: 'Buckethead'})
// 'Buckethead'

文字列を大文字にする関数を書きましょう。

大文字=(文字列)=> string.toUpperCase()
uppercase( 'Buckethead')
//「バケットヘッド」

したがって、人の名前を取得して大文字にする場合は、次のようにします。

name = getName({name: 'Buckethead'})
大文字(名前)
//「バケットヘッド」

それは問題ありませんが、その中間変数名を削除しましょう。

uppercase(getName({name: 'Buckethead'}))

より良いが、私はそのネストが好きではありません。混みすぎます。文字列の最初の6文字を取得する関数を追加する場合はどうなりますか?

get6Characters =(string)=> string.substring(0、6)
get6Characters( 'Buckethead')
// 'バケツ'

その結果:

get6Characters(uppercase(getName({name: 'Buckethead'})))
'バケツ'

本当に夢中になって、文字列を逆にする関数を追加しましょう。

逆=(文字列)=>文字列
  。スプリット('')
  。逆()
  .join( '')
reverse( 'Buckethead')
// 'daehtekcuB'

今、私たちは持っています:

reverse(get6Characters(uppercase(getName({name: 'Buckethead'}))))
// 'TEKCUB'

それは少し…多くを得ることができます。

パイプを助けて!

関数内で関数をジャムしたり、中間変数の束を作成したりする代わりに、すべてのものをパイプしましょう!

パイプ(
  getName、
  大文字、
  get6Characters、
  逆
)({name: 'Buckethead'})
// 'TEKCUB'

純粋な芸術。仕事リストのようなものです!

それをステップスルーしましょう。

デモのために、Eric Elliottの関数型プログラミングの記事の1つからのパイプ実装を使用します。

パイプ=(... fns)=> x => fns.reduce((v、f)=> f(v)、x)

私はこの小さなワンライナーが大好きです。

残りのパラメータを使用して、それに関する私の記事を参照して、n個の関数をパイプできます。各関数は前の関数の出力を取得し、すべて単一の値に縮小します。

そして、上記と同じように使用できます。

パイプ(
  getName、
  大文字、
  get6Characters、
  逆
)({name: 'Buckethead'})
// 'TEKCUB'

パイプを展開し、デバッガーステートメントを追加して、行ごとに説明します。

パイプ=(...関数)=>(値)=> {
  デバッガ;
  関数を返す
    .reduce((currentValue、currentFunction)=> {
       デバッガ;
       return currentFunction(currentValue);
    }、値)
}

この例でpipeを呼び出して、驚異を広げましょう。

ローカル変数を確認してください。 functionsは4つの関数の配列であり、値は{name: 'Buckethead'}です。

残りのパラメーターを使用しているため(再び、私の記事seeを参照)、パイプでは任意の数の関数を使用できます。ループして、それぞれを呼び出します。

次のデバッガーでは、reduceの中にいます。これは、currentValueがcurrentFunctionに渡されて返される場所です。

currentFunctionは任意のオブジェクトの.nameプロパティを返すため、結果は「Buckethead」です。それはreduceで返されます。つまり、次回は新しいcurrentValueになります。次のデバッガーを見てみましょう。

現在、currentValueは「Buckethead」です。これは前回返されたものだからです。 currentFunctionは大文字なので、「BUCKETHEAD」が次のcurrentValueになります。

同じ考えで、「BUCKETHEAD」の最初の6文字を抜き取り、次の機能に引き渡します。

reverse( ‘。aedi emaS’)

これで完了です!

compose()はどうですか?

それはただ反対方向へのパイプです。

したがって、上記のパイプと同じ結果が必要な場合は、反対のことを行います。

compose(
  逆、
  get6Characters、
  大文字、
  getName、
)({name: 'Buckethead'})

getNameがチェーンの最後で、逆が最初であることに注意してください。

同じ記事のMagical Eric Elliottの好意による作曲の簡単な実装を次に示します。

compose =(... fns)=> x => fns.reduceRight((v、f)=> f(v)、x);

演習として、デバッガーを使用してこの機能を拡張したままにします。それをいじって、使って、感謝します。そして最も重要なことは、楽しんでください!

次回まで!

気を付けて、
ヤゼド・バザドゥ