みみぺんブログ

WEBデザイナー、エンジニア、プログラマー向けの記事を投稿します

カリー化・関数の部分適用について ~関数をどんどん使いまわしていこう!~【JavaScript初心者入門】

JavaScriptのカリー化・関数の部分適用について ~関数をどんどん使いまわしていこう!~

はじめに

こんにちは、かずん(@kazoonLab)です。

前回の記事では、JavaScriptの高階関数についてご紹介しました。

今回は、前回の記事の続きで、JavaScriptの「カリー化」と「関数の部分適用」についてご紹介します。

かずん

この記事を読むと、JavaScriptのカリー化関数と関数の部分適用についてわかるよ!/p>



カリー化とは

カリー化の説明の前に、まず高階関数の復習から入りましょう。

高階関数とは、「関数を引数にしたり、関数を戻り値とする関数」のことです。サンプルコードを見てみましょう。

const hof = function (m) {
  return function (n) {
    return m + n;
  }
}

// アロー関数で書いてみる
const hofArrow = m => {
  return n => {
    return m + n
  }
}

// return をなくしてシンプルに
const hofSimple = m => n => m + n;

// hofSimpleを呼び出す
console.log(hofSimple(3)(4));  // --> 7



関数hofは、引数にnをとり、「引数にmをとり、n+mの結果を返す関数」を返します。

関数hofArrowはアロー関数を使って書いた形、関数hofSimpleはそこからreturnを省略した形です。できるだけシンプルな形で書いていきましょう。

ところで、hofSimpleを呼び出すとき、(3)(4)と引数が2つ続いていることにお気づきでしょうか。

hofSimple(3)が「nを引数にとり、n + 3を返す関数」なため、もうひとつ引数(n)が必要になります。(ここでは、n = 4を代入しています。)

このように、高階関数の引数を一つずつ返していって、引数が複数つながっている状態にすることを「カリー化」と呼びます。

続いて、カリー化された関数の部分適用について見ていきましょう。

関数の部分適用とは

const curry = m => n => m + n;

// 2を足す関数
const plusTwo = curry(2);
console.log(plusTwo(3));  // --> 5 (2 + 3)
console.log(plusTwo(5)); // --> 7 (2 + 5)

// 5を足す関数
const plusFive = curry(5);



今回は、関数curryの引数mに2が入ったとき、その戻り値をplusTwoという変数に代入(=関数に名前をつけている)しています。

この時、関数plusTwo(n)は「引数nをとり、2 + nを返す関数」になりますね。

このように、カリー化された関数の任意の引数を固定し、別の関数を作ることを「関数の部分適用」といいます。

サンプルコードでは、他にも5を足す関数plusFive(n)を定義しています。当然、7を足す関数、9を足す関数も関数curry(m)(n)を使って定義できますね。

どんなところで使う?

一見便利そうだなあと思うんですが、使いどころは難しいですね。。

例えばReactだと、Material UI のwithStyles()なんかが高階関数にあたります。

const styles = {
  comp: {
    fontSize: 12,
  }
}

const Wrapped = () => <p className={classes.root}>wrapped</p>

export default withStyles(styles)(Wrapped);



最初の引数であてたいstyleを、次の引数であて先のコンポーネントを指定しています。 styleが固定なら、withStyles(style)を変数に代入して、各コンポーネントでimport/exportして使いまわすことができる、、とかでしょうかね。

自分自身でもよりいい例が見つかったら、この記事は更新していこうかと思います。

最後までご覧いただきありがとうございます。

この記事がいいなっと思ったら読者登録をお願いいたします♪



【ツイッターでは主に、仕事や技術系の内容をつぶやいています】 技術者の方ともっと繋がりたいっす!お気軽にフォローもお願いします!
かなきち(@kanakichi0801)
かずん(@kazoonLab)