タイトルにあるようにこんな感じの書き方に出くわした。
const nanikore = (hoge) => (fuga) => {
return hoge * fuga
}
なんじゃこりゃ...
引数が二つある....
ということで調べてみました。
結論から
タイトルにもあるようにこういった書き方をカリー化というらしい。
カリー化とは段階的に引数を渡すような構造の関数を作るためのテクニック。
つまりカリー化された関数とは全ての引数(パラメータ)が揃うまで
処理結果を遅延することができる。
上記の解釈で記事を書いたが全然違うかったので訂正。
タイトルにある ()=>()=> は
引数を段階的に渡せるような構造の関数を作るための書き方。
要は関数を返す関数で、関数を返すたびに受け取った引数を部分適用していき
一番最後の関数の処理が終わった時に結果を返す。
const add = (a) => (b) => (c) => {
console.log(a + b + c)
}
const addOne = add(1)
const addThree = addOne(2)
addThree(3) //6 ここで初めて計算結果が出力される
add(1)(2)(3) //6 一気に全ての引数を渡すこともできる
ちなみにカリー化とは
段階的にでも引数を複数渡せてしまうと 「カリー化」ではない。
「カリー化」とはあくまでも引数をひとつだけとる関数にすること。
この制約のためにシンプルな構造となり、可読性が良くなったりします。
詳しくはコメント欄にて@ttatsfさんが
メリデメや実用性について解説してくれています。
とても勉強になりました。
使い方
パラメータを設定した関数を再利用したい場合
const shipp = (addres) => (obj) => {
console.log(`宛先は${address} ${obj}を送りました`)
}
const shippToTokyo = shipp('東京')
shippToTokyo('本') // 宛先は東京 本を送りました"
shippToTokyo('洋服') // 宛先は東京 洋服を送りました"
const shippToOsaka = shipp('大阪')
shippToOsaka('本') // 宛先は大阪 本を送りました"
shippToOsaka('靴') // 宛先は大阪 靴を送りました"
引数が多すぎる場合
//引数の多い関数
const add = (a, b, c, d, e) => a + b + c + d + e
//既存の関数をカリー化する関数 ※正しくは部分適用化
const curry = (funk) => (...args) => {
if (args.length >= funk.length) { //実際に渡された引数がfunkに必要な引数より多い場合
return funk(...args) //funkを実行
}
//引数が足りない場合は引数を追加した新しい関数を返す
return (...args2) => curry(funk)(...args, ...args2)
}
//カリー化 ※正しくは部分適応化
const curriedAdd = curry(add)
const addFive = curriedAdd(5)
console.log(addFive(3)(2)(5)(5)) // 20
参考にした記事
https://zenn.dev/nekoniki/articles/5b7980fac91048775931
https://jp.quora.com/kansuu-no-kari-ka-ha-jitsuyou-teki-ni-ha-donna-tokini-yaku-tachi-masu-ka