前回の記事、
ワイ「なに!?型のズレを吸収できるやと!?」
の続きやで!
ある日、コソコソと配列をいじるワイ
ワイ「うーん、これではまた駄目や・・・」
ハスケル子「やめ太郎さん、さっきから何か配列いじってますけど」
ハスケル子「それ何の配列なんですか?」
let vacationOrderList =
["ハリー先輩", "カリポリ君", "やめ太郎", "ハリー先輩", "カリポリ君", "やめ太郎", ...];
ワイ「↑これはな、ワイのチームのみんなの有給休暇の順番や」
ワイ「弊社は有給取り放題やから」
ワイ「チームのみんなで順番に有給休暇を取得しまひょ〜、いうて」
ワイ「有給の順番表を表示するための簡単なWebページを作ったんや」
ハスケル子「はあ」
ワイ「さっきの配列を元に、画面上に有給の順番リストを表示して」
ワイ「そのページを見ながら、みんなで順番に有給を取っていくんや」
ハスケル子「はい」
ハスケル子「それで、やめ太郎さんはどうして」
ハスケル子「その有給休暇の配列をいじってたんですか?」
ワイ「そ、それは・・・」
ハスケル子「それは?」
ワイ「・・・たいんや・・・」
ハスケル子「何ですか?ハッキリ言ってください」
ワイ「・・・ワイの休みを・・・増やしたいんや・・・」
ハスケル子「そうですか・・・」
ワイ「せやから、有給の順番リストが画面に表示される前に」
ワイ「ちょっと処理を挟んで、ワイの休みを増やそうとしてたんや」
ハスケル子「・・・」
ハスケル子「それで、何がうまく行かないんですか?」
ワイ「聞いてくれるか?」
ワイ「とりあえず、有給の順番を改ざんしようと思ってmap()
メソッドを実行したんや」
vacationOrderList =
vacationOrderList
.map(name => name === "カリポリ君"? "やめ太郎": name);
ハスケル子「カリポリ君の休みを全て、やめ太郎さんの休みに書き換えたわけですね」
ハスケル子「完璧な処理じゃないですか」
ハスケル子「何が駄目だったんですか?」
ワイ「それがな・・・」
カリポリ君「あれ?」
カリポリ君「オレの休み、1日も無くなってんだけど」
カリポリ君「代わりに、やめ太郎の休みメッチャ増えてんだけど」
ワイ「・・・ってな感じで、バレてもうたんや・・・」
ハスケル子「さすがカリポリさん、鋭いですね」
ワイ「誰かの休みを丸ごとワイの休みに置き換えるような」
ワイ「そんなダイナミックな処理をするとバレてしまうみたいなんや」
ワイ「せやから、もうちょっと自然にワイの休みを増やしたいんや・・・」
ワイ「そんなこと、不可能なんかな・・・」
ハスケル子「可能ですが?」
ワイ「まじかいな」
ハスケル子「このまえ使ったflat()
を使うんですよ!」
ワイ「ほお」
ハスケル子「まず、イメージをお伝えするために」
ハスケル子「map()
を使って書いてみますね」
vacationOrderList =
vacationOrderList
.map(name => name === "やめ太郎"? [name, name, name]: name);
ワイ「ファッ!?」
ワイ「そんなことしたら、配列が↓こうなってしまうやないか!!!」
["ハリー先輩", "カリポリ君", ["やめ太郎", "やめ太郎", "やめ太郎"], "ハリー先輩", "カリポリ君", ["やめ太郎", "やめ太郎", "やめ太郎"], ...]
ワイ「ワイのところだけ配列になってしまうから」
ワイ「即バレやでこんなもん!」
ハスケル子「そこでflat()
を使うんです」
vacationOrderList =
vacationOrderList
.map(name => name === "やめ太郎"? [name, name, name]: name)
.flat();
ハスケル子「flat()
は配列を1階層フラットにしてくれるので」
ハスケル子「配列は↓こうなります」
["ハリー先輩", "カリポリ君", "やめ太郎", "やめ太郎", "やめ太郎", "ハリー先輩", "カリポリ君", "やめ太郎", "やめ太郎", "やめ太郎", ...]
ワイ「うおお、自然や・・・!」
ワイ「限りなく自然や・・・!」
社長「(いや不自然やろ)」
社長「(なんでお前の休みだけメッチャ増えてんねん・・・)」
ハスケル子「しかも、map()
してflat()
している部分は」
ハスケル子「flatMap()
メソッドでまとめられます」
vacationOrderList =
vacationOrderList
.flatMap(name => name === "やめ太郎"? [name, name, name]: name);
ワイ「おお・・・!」
ワイ「これがこのまえ言うてたflatMap()
かいな」
ワイ「こんな都合のいいメソッドが・・・!?」
ワイ「まさに、ワイの有給を増やすためのメソッドやないかい・・・」
社長「(いや違うやろ・・・)」
ハスケル子「まあ、何でもいいんですけど」
ハスケル子「map()
やfilter()
ではできない、配列の要素を増やすような処理を」
ハスケル子「条件に応じてできるのが、flatMap()
の素敵なところですね」
ワイ「そうか」
ワイ「map()
やと要素数は同じままやし」
ワイ「filter()
やと要素数は減るだけやもんな」
ハスケル子「そうですね」
ワイ「つまり、flatMap()
を使うと・・・」
name => [name, name, name]
ワイ「↑こういう、戻り値として配列を返す関数を・・・」
name => ...[name, name, name]
ワイ「↑こんな風に、展開しながら返してくれる関数に変身させてくれる・・・」
ワイ「そんなイメージで使えるな!」
ハスケル子「関数を変身させる・・・まさにそうですね」
ハスケル子「普通、関数の戻り値は1つですけど」
ハスケル子「flatMap()
メソッドに渡されたコールバック関数は」
ハスケル子「複数の値を返せる、つまり多値返却ができる関数に変身します」
ワイ「おお・・・!」
ワイ「前回ハスケル子ちゃんが言うてた・・・」
ハスケル子「もっと楽しい、
flatMap()
なんていうメソッドもありますよ」
ハスケル子「map()
してflat()
してくれるやつです」
ハスケル子「まるで関数が変身するみたいですよ」
ワイ「・・・ていうのはこういうことやったんやな!」
ハスケル子「はい!」
ワイ「確かに楽しいな!」
ハスケル子「はい!」
社長「(いや休みが増えてテンション上がっとるだけやろ)」
まとめ
- いっぱい休めた。
社長「いやそれがまとめかい!」
まとめ(やり直し)
-
map()
してflat()
するならflatMap()
を使える。 -
flatMap()
を使ったら、配列の要素を増やすような処理ができた。 - 普通の関数を、多値返却ができる関数に変身させてくれる感じだった。
- 戻り値で3つも有給を返せるみたいで、楽しくなった。
ワイ「ありがとうな、ハスケル子ちゃん」
ワイ「いっぱい休んで、しっかりプログラミングの勉強さしてもらうわ!」
ハスケル子「はい!」
社長「(有給やなくて、悠久の休み1をくれたろか・・・)」
〜おしまい〜
続編もよろしくやで!
→4歳娘「パパ、そんなときはクロージャが役に立つんじゃない?」
参考文献
注意
- もちろんIEでは使えへんから、Babelとか使ってな!(定期)
- ほんまに改ざんとかしたらアカンで!
-
悠久の休み・・・解雇のことです。 ↩