SlideShare a Scribd company logo
Submit Search
Upload
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 4 章
Report
Share
L
Last Arrow
-- at UEC, Tokyo (Student)
Follow
•
6 likes
•
3,417 views
1
of
83
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 4 章
•
6 likes
•
3,417 views
Report
Share
Download Now
Download to read offline
Internet
Topotal部外者ですが参加した、第 2 回「JavaScript で関数型プログラミング言語」輪読会の第 4 章の発表資料です
Read more
L
Last Arrow
-- at UEC, Tokyo (Student)
Follow
Recommended
たのしい高階関数 by
たのしい高階関数
Shinichi Kozake
11.8K views
•
81 slides
たのしい関数型 by
たのしい関数型
Shinichi Kozake
6.2K views
•
94 slides
Material by
Material
_TUNE_
3.5K views
•
86 slides
関数プログラミング入門 by
関数プログラミング入門
Hideyuki Tanaka
21.8K views
•
101 slides
「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14) by
「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)
parrotstudio
15.3K views
•
56 slides
磯野ー!関数型言語やろうぜー! by
磯野ー!関数型言語やろうぜー!
Ra Zon
10.3K views
•
40 slides
More Related Content
What's hot
関数型プログラミング入門 with OCaml by
関数型プログラミング入門 with OCaml
Haruka Oikawa
12.4K views
•
105 slides
Real World OCamlを読んでLispと協調してみた by
Real World OCamlを読んでLispと協調してみた
blackenedgold
4K views
•
39 slides
これから Haskell を書くにあたって by
これから Haskell を書くにあたって
Tsuyoshi Matsudate
5.8K views
•
175 slides
研究会20140618:進捗と闇Pythonistaのワンライナーテクニックを少々 by
研究会20140618:進捗と闇Pythonistaのワンライナーテクニックを少々
Peinan ZHANG
3.7K views
•
21 slides
Java x Groovy: improve your java development life by
Java x Groovy: improve your java development life
Uehara Junji
2.3K views
•
77 slides
Freer Monads, More Extensible Effects by
Freer Monads, More Extensible Effects
Hiromi Ishii
6.3K views
•
124 slides
What's hot
(20)
関数型プログラミング入門 with OCaml by Haruka Oikawa
関数型プログラミング入門 with OCaml
Haruka Oikawa
•
12.4K views
Real World OCamlを読んでLispと協調してみた by blackenedgold
Real World OCamlを読んでLispと協調してみた
blackenedgold
•
4K views
これから Haskell を書くにあたって by Tsuyoshi Matsudate
これから Haskell を書くにあたって
Tsuyoshi Matsudate
•
5.8K views
研究会20140618:進捗と闇Pythonistaのワンライナーテクニックを少々 by Peinan ZHANG
研究会20140618:進捗と闇Pythonistaのワンライナーテクニックを少々
Peinan ZHANG
•
3.7K views
Java x Groovy: improve your java development life by Uehara Junji
Java x Groovy: improve your java development life
Uehara Junji
•
2.3K views
Freer Monads, More Extensible Effects by Hiromi Ishii
Freer Monads, More Extensible Effects
Hiromi Ishii
•
6.3K views
Lisp tutorial for Pythonista : Day 2 by Ransui Iso
Lisp tutorial for Pythonista : Day 2
Ransui Iso
•
2.1K views
Thinking in Cats by Eugene Yokota
Thinking in Cats
Eugene Yokota
•
7.2K views
あなたのScalaを爆速にする7つの方法(日本語版) by x1 ichi
あなたのScalaを爆速にする7つの方法(日本語版)
x1 ichi
•
14.2K views
LLdeade Python Language Update by Atsushi Shibata
LLdeade Python Language Update
Atsushi Shibata
•
2.4K views
Java SE 8 lambdaで変わる プログラミングスタイル by なおき きしだ
Java SE 8 lambdaで変わる プログラミングスタイル
なおき きしだ
•
18K views
(define)なしで再帰関数を定義する by blackenedgold
(define)なしで再帰関数を定義する
blackenedgold
•
2.4K views
Scalaで萌える関数型プログラミング[1.1.RC1] by Ra Zon
Scalaで萌える関数型プログラミング[1.1.RC1]
Ra Zon
•
2.1K views
命令プログラミングから関数プログラミングへ by Naoki Kitora
命令プログラミングから関数プログラミングへ
Naoki Kitora
•
3.8K views
関数型プログラミング in javascript by Ryuma Tsukano
関数型プログラミング in javascript
Ryuma Tsukano
•
18.5K views
Scalaで型クラス入門 by Makoto Fukuhara
Scalaで型クラス入門
Makoto Fukuhara
•
6.4K views
The Why and How of Java8 at LINE Fukuoka by Youhei Nitta
The Why and How of Java8 at LINE Fukuoka
Youhei Nitta
•
9.7K views
Haskell勉強会 in ie by maeken2010
Haskell勉強会 in ie
maeken2010
•
1.4K views
サーバーサイドでの非同期処理で色々やったよ by koji lin
サーバーサイドでの非同期処理で色々やったよ
koji lin
•
359.6K views
BOF1-Scala02.pdf by Hiroshi Ono
BOF1-Scala02.pdf
Hiroshi Ono
•
344 views
Similar to 【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 4 章
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 2 章 by
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 2 章
YOSHIKAWA Ryota
8.6K views
•
48 slides
JavaScript 講習会 #1 by
JavaScript 講習会 #1
Susisu
2.8K views
•
60 slides
FP習熟度レベルとFSharpxのIteratee by
FP習熟度レベルとFSharpxのIteratee
pocketberserker
1.7K views
•
101 slides
Scalaで萌える関数型プログラミング[完全版] by
Scalaで萌える関数型プログラミング[完全版]
Ra Zon
6.9K views
•
52 slides
po-6. 繰り返し実行(ループ),ステップ実行 by
po-6. 繰り返し実行(ループ),ステップ実行
kunihikokaneko1
259 views
•
41 slides
Introduction of "the alternate features search" using R by
Introduction of "the alternate features search" using R
Satoshi Kato
3.1K views
•
26 slides
Similar to 【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 4 章
(20)
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 2 章 by YOSHIKAWA Ryota
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 2 章
YOSHIKAWA Ryota
•
8.6K views
JavaScript 講習会 #1 by Susisu
JavaScript 講習会 #1
Susisu
•
2.8K views
FP習熟度レベルとFSharpxのIteratee by pocketberserker
FP習熟度レベルとFSharpxのIteratee
pocketberserker
•
1.7K views
Scalaで萌える関数型プログラミング[完全版] by Ra Zon
Scalaで萌える関数型プログラミング[完全版]
Ra Zon
•
6.9K views
po-6. 繰り返し実行(ループ),ステップ実行 by kunihikokaneko1
po-6. 繰り返し実行(ループ),ステップ実行
kunihikokaneko1
•
259 views
Introduction of "the alternate features search" using R by Satoshi Kato
Introduction of "the alternate features search" using R
Satoshi Kato
•
3.1K views
ECMAScript6による関数型プログラミング by TanUkkii
ECMAScript6による関数型プログラミング
TanUkkii
•
11.9K views
Clojure programming-chapter-2 by Masao Kato
Clojure programming-chapter-2
Masao Kato
•
1.1K views
Dotnetconf2017 by Yoshiyuki Taniguchi
Dotnetconf2017
Yoshiyuki Taniguchi
•
102 views
おいしいLisp by Kent Ohashi
おいしいLisp
Kent Ohashi
•
1.2K views
これからの「言語」の話をしよう ―― 未来を生きるためのツール by Nobuhisa Koizumi
これからの「言語」の話をしよう ―― 未来を生きるためのツール
Nobuhisa Koizumi
•
1.3K views
Control.Arrow by haru haru
Control.Arrow
haru haru
•
134 views
Replace Output Iterator and Extend Range JP by Akira Takahashi
Replace Output Iterator and Extend Range JP
Akira Takahashi
•
1.6K views
JavaScript入門 by Ryo Maruyama
JavaScript入門
Ryo Maruyama
•
1.1K views
Deep learning Libs @twm by Yuta Kashino
Deep learning Libs @twm
Yuta Kashino
•
18.3K views
Fork/Join Framework。そしてLambdaへ。 by Yuichi Sakuraba
Fork/Join Framework。そしてLambdaへ。
Yuichi Sakuraba
•
2K views
F#で関数型言語に触れてみよう by wof moriguchi
F#で関数型言語に触れてみよう
wof moriguchi
•
8.2K views
すごいHaskell読書会#10 by Shin Ise
すごいHaskell読書会#10
Shin Ise
•
1.6K views
Nagoya.R #11 入門者講習 by Yusaku Kawaguchi
Nagoya.R #11 入門者講習
Yusaku Kawaguchi
•
2.6K views
第三回ありえる社内勉強会 「いわががのLombok」 by yoshiaki iwanaga
第三回ありえる社内勉強会 「いわががのLombok」
yoshiaki iwanaga
•
14.1K views
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 4 章
1.
JavaScriptで学ぶ 関数型プログラミング 第4章"高階関数 小式澤!篤!(@lastarrow21) Topotal'輪読会 2015%02%11 KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 1
2.
出典 • JavaScriptで学ぶ関数型プログラミング • Michael/Fogus/著 •
和田/祐一郎/訳 • O'REILLY/®/オライリー・ジャパン/出版 KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 2
3.
前置き KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 3
4.
前置き • 自由変数をわかりやすくするために、変数名を全て大文字表記 にしている • 一般的なプログラミングスタイルでは推奨されない KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会
4
5.
(復習) クロージャ 3.5.1%節 KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 5
6.
クロージャ • プログラム内で環境を共有する仕組み • スコープの実行完了後でも内部情報を保持し続ける関数 function
makeAdder(CAPTURED) { // CAPTURED : 自由変数 (確保される変数) return function(free) { return free + CAPTURED }; } var add10 = makeAdder(10); // add10 が"10"を確保 add10(32); // => 42 KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 6
7.
4章"高階関数 KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 7
8.
高階関数 • 前提 • 第一級のデータ型である •
次のうち、少なくともどちらか一方を満たす • 引数として関数をとる • 関数を戻り値として返す KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 8
9.
高階関数 • 前提 • 第一級のデータ型である •
次のうち、少なくともどちらか一方を満たす • 引数として関数をとる"!"まずはここから考える • 関数を戻り値として返す KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 9
10.
4.1$引数として関数を取る関数 KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 10
11.
引数として関数を取る関数 • 既に(4章よりも前に)登場している • _.map、_.reduce、_.filter •
関数を引数に取ることに関して、もう少し詳しく考える KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 11
12.
4.1.1$関数を渡すことを考える max、finder、best KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 12
13.
「関数を渡す」と何ができるのか • 配列などから最大値を返す関数"_.max console.log(_.max([1, 2,
3, 4, 5])); // => 5 • 第二引数に、関数を渡すことができる"!"高階関数 var people = [{ name : "Fred", age : 65 }, { name : "Lucy", age : 36 }]; console.log(_.max(people, function(p){ return p.age })); // => {name : "Fred", age : 65} KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 13
14.
_.maxの考察 • 関数を引数に取れる • 任意のオブジェクト同士を比較する手段を提供している •
関数を構築する上で有用 • 常に">"(大なり)を用いて比較している • この制限により、本当に関数型であるとはいえない KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 14
15.
「良い」値を返す関数finder • 第1,$第2引数は関数 • 比較するデータから比較できるように値を作る関数 •
2つの値を比較して、そこから「良い」値を返す関数 • 第3引数は比較するデータを含むオブジェクトの配列 KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 15
16.
「良い」値を返す関数finderの実装 function finder(valueFun, bestFun,
coll) { return _.reduce(coll, function(best, current) { var bestValue = valueFun(best); var currentValue = valueFun(current); return (bestValue === bestFun(bestValue, currentValue)) ? best : current; }); } finder(_.identity, Math.max, [1, 2, 3, 4, 5]); // => 5 KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 16
17.
「良い」値を返す関数finderの他の用例 • プロパティ名ageを比較して最大のものを「良い」とする finder(plucker('age'), Math.max,
people); // => { name : "Fred", age : 65 } • プロパティ名nameの最初の文字がLであるものを「良い」とす る finder(plucker('name'), function(x, y){ return (x.charAt(0) === "L") ? x : y }, people); // => { name : "Lucy", age : 36 } KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 17
18.
「良い」値を返す関数finderの考察 • 比較の仕方を関数で指定できる • 様々なタイプの「最良の値を探す」関数を生成できる •
ロジックを複製している箇所がある // finder関数内 return (bestValue === bestFun(bestValue, currentValue)) ? best : current; // 「最良の値を探す」bestFun関数内 return (x.charAt(0) === "L") ? x : y; KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 18
19.
ロジックの複製を回避するために • 最良の値を判定する関数は • 最初の引数が2つ目の引数よりも良い場合にtrueを返す •
渡された引数を比較できる形まで紐解く方法を知っている KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 19
20.
よりエレガントな関数bestの実装 function best(fun, coll){ return
_.reduce(coll, function(x, y){ return fun(x, y) ? x : y; }); } console.log(best(function(x, y){ return x > y; }, [1, 2, 3, 4, 5])); // => 5 KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 20
21.
より良い値を探す関数の考察 • 2つの関数を引数に取る関数#finder • ロジックの重複が発生した •
ロジックの重複を削除することに一般化した関数#best • 引き締まった KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 21
22.
より一般的な関数に作り直すには 4.1.2%関数を渡すことを更に考える KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 22
23.
指定した回数だけ値を格納する関数!repeat function repeat(times, VALUE)
{ return _.map(_.range(times), function() { return VALUE; }); } repeat(4, "Major"); // => ["Major", "Major", "Major", "Major"] KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 23
24.
関数!repeat!の考察 • とても素直な実装 • 「一般的な繰り返し」とは言えない KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会
24
25.
関数!repeat!の考察 • とても素直な実装 • 「一般的な繰り返し」とは言えない •
計算を繰り返したいことがある KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 25
26.
関数!repeat!の考察 • とても素直な実装 • 「一般的な繰り返し」とは言えない •
計算を繰り返したいことがある 「値ではなく関数を使え」 KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 26
27.
繰り返し計算した結果を格納する関数!repeatedly function repeatedly(times, fun)
{ return _.map(_.range(times, fun); } repeatedly(3, function() { return Math.floor(Math.random() * 10 + 1); }); // => [1, 3, 8] KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 27
28.
関数!repeatedly!の考察 • 関数を呼ぶことによって任意の値が格納されるようになった • もちろん固定値も格納できる KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会
28
29.
関数!repeatedly!の考察 • 関数を呼ぶことによって任意の値が格納されるようになった • もちろん固定値も格納できる repeatedly(3,
function() { return "Odeley!"; }); // => { "Odeley!", "Odeley!", "Odeley!" } KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 29
30.
関数!repeatedly!の考察 • 関数を呼ぶことによって任意の値が格納されるようになった • もちろん固定値も格納できる repeatedly(3,
function() { return "Odeley!"; }); // => { "Odeley!", "Odeley!", "Odeley!" } • 引数に関係なく固定値を返す関数はよくある話 (詳しくは5章にて) KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 30
31.
「値ではなく関数を使え」(再掲) KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 31
32.
「値ではなく関数を使え」 • 関数"repeatedly"で、格納される値が関数によって任意に生成 されるようになった • ただし、反復回数がいつもわかるとは限らない //
for文による例 for (let i = 2; i <= 1024; i = i * 2) { console.log(i); } // => 2 4 8 16 32 64 128 256 512 1024 // 10回繰り返された KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 32
33.
さらに進化した関数!iterateUntil • 第一引数"fun • 格納する値を生成する関数 •
第二引数"check • 繰り返しが終了すべき時にfalseを返す関数 • 第三引数"init KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 33
34.
さらに進化した関数!iterateUntil function iterateUntil(fun, check,
init) { var ret = []; var result = fun(init); while (check(result)) { ret.push(result); result = fun(result); } return ret; } KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 34
35.
iterateUntil!の使用例 iterateUntil(function(n) { return
n * 2; }, function(n) { return n <= 1024; }, 1); // => [ 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 ] KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 35
36.
関数!iterateUntil!の考察 • 繰り返し条件が関数"check"の結果依存になった • 実質無制限 •
終了条件だけ知っている場合も用いれる !!関数!repeatedly!の1段階上の存在となった KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 36
37.
高階関数 • 前提 • 第一級のデータ型である •
次のうち、少なくともどちらか一方を満たす • 引数として関数をとる • 関数を戻り値として返す"!"次はこっち KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 37
38.
4.2$他の関数を返す関数 KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 38
39.
今までの関数を返す関数 • makeAdder • 自由変数と引数の和を返す関数を返す •
complement • 引数にとった関数の真偽値判定が逆になる関数を返す • plucker • 引数にとった値をキーとして対応する値を返す関数を返す KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 39
40.
定数を返す関数!always • 関数"repeatedly"では引数を無視して値を返す関数を使った • 定数を返す関数":"k"と呼ばれる •
ここでは"always"と呼ぶ function always(VALUE) { return function() { return VALUE; }; } KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 40
41.
クロージャ使用上の注意!(1/2) • 関数は常に唯一の値を生成する • 自由変数VALUEに束縛された戻り値は常に等しい'[Braithwaite,' '13] var
f = always(function(){}); f() === f(); // => true KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 41
42.
クロージャ使用上の注意!(2/2) • 新しく生成されたクロージャは、それぞれ異なる値を返す var f
= always(function(){}); var g = always(function(){}); f() === g(); // => false KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 42
43.
関数!always!の使用例 • 無名関数の代わりに使うとコードがすっきりする repeatedly(3, always("Odelay!")); //=>
[ "Odelay!", "Odelay!", "Odelay!" ] KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 43
44.
関数!invoker • 第一引数"NAME • 第二引数のMETHODを実行する対象 •
第二引数"METHOD • 実行するメソッド名 KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 44
45.
関数!invoker!の実装 function invoker (NAME,
METHOD) { return function(target /* args ... */) { if (!existy(target)) fail("Must provide a target"); var targetMethod = target[NAME]; var args = _.rest(arguments); return doWhen((existy(targetMethod) && METHOD === targetMethod), function() { return targetMethod.apply(target, args); }); }; } KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 45
46.
関数!invoker!の使用例 var rev =
invoker('reverse', Array.prototype.reverse); _.map([[1,2,3]], rev); //=> [ [ 3,2,1 ] ] KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 46
47.
関数!invoker!の考察 • invoker"が返す関数はクロージャ • reverse"などを保持しておいて、後で使用する"(revの設定 データ) •
関数"always"とは違って、特別な処理を行う関数を返す • 関数型プログラミングでは、オブジェクトを引数に取ることを 好む KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 47
48.
4.2.1%引数を高階関数に確保する • Ques&on.*なぜ関数を返す関数を生成するの? • Hint.*高階関数に渡す引数は、返される関数の設定項目 var
add100 = makeAdder(100); add100(38); // => 138 • makeAdder関数に100という値を設定したものをadd100とい う名前に束縛した • ここからは、変数を確保した関数を返す関数の話 KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 48
49.
4.2.2$大義のために変数を確保する KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 49
50.
例!:!ユニークに文字列を生成する関数 素朴な実装の場合 function uniqueString(len) { return
Math.random().toString(36).substr(2, len); }; uniqueString(10); //=> liydklvjbk KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 50
51.
ランダム文字列に接頭辞を付けたくなったら? 関数!uniqueString!を修正する function uniqueString(prefix) { return
[prefix, new Date().getTime()].join(''); }; uniqueString("argento"); //=> "argento1356107740868" KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 51
52.
また要件が変わった! • 要件":"指定した文字列に連番をつけたもの function makeUniqueStringFunction(start)
{ var COUNTER = start; // suffixの開始番号 return function(prefix) { return [prefix, COUNTER++].join(''); } }; KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 52
53.
関数!makeUniqueStringFunction!の実行例 // 連番は0からスタート var uniqueString
= makeUniqueStringFunction(0); uniqueString("dari"); //=> "dari0" uniqueString("dari"); //=> "dari1" KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 53
54.
オブジェクトによる!makeUniqueStringFunction!の 再実装 var generator =
{ count: 0, uniqueString: function(prefix) { return [prefix, this.count++].join(''); } }; generator.uniqueString("bohr"); // => bohr0 generator.uniqueString("bohr"); // => bohr1 KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 54
55.
オブジェクト!generator!の危険性 • count"プロパティに再代入すると"! generator.counter =
"gotcha"; console.log(generator.uniqueString("bohr")); // --> bohrNaN KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 55
56.
オブジェクト!generator!の改良 var omgenerator =
( function(init) { var COUNTER = init; return { uniqueString: function(prefix) { return [prefix, COUNTER++].join(''); } } })(0); print(omgenerator.uniqueString("lichking-")); KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 56
57.
オブジェクト!omgenerator!の考察 • COUNTER"の隠 には成功した •
非常に美しくない • ECMAScript.next"では頑張っている • makeUniqueStringFunction"のようにクロージャを使えば 美しい • 参照透明性がない KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 57
58.
参照透明性 • 関数が返す結果がその引数によってのみ左右されること • makeUniqueStringFunction"が返す値は自身の実行回数依 存 •
何回呼び出したかは知ることは不可能 • 詳しくは7章で KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 58
59.
「存在しない状態」 var nums =
[1,2,3,null,5]; _.reduce(nums, function(total, n) { return total * n }); //=> 0 doSomething({ WhoCares: 42, critical: null }); //!!" KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 59
60.
「存在しない状態」に備える関数!fnull • 「存在しない状態」に対する防御のための関数 • fnull"の引数は関数と1つ以上のデフォルト値 •
fnull"が返す関数の引数に"null"や"undefined"が混ざってい たら、デフォルト値がかわりに用いられる • デフォルト値の代入は、必要なときが来るまで遅延される KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 60
61.
関数!fnull!の実装 function fnull(fun /*,
default value */) { var defaults = _.rest(arguments); return function(/* args */) { var args = _.map(arguments, function(e, i) { return existy(e) ? e : defaults[i]; }); return fun.apply(null, args); }; } KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 61
62.
関数!fnull!の使用例(1)!:!数値 null var nums
= [1,2,3,null,5]; var safeMult = fnull( function(total, n) { return total * n }, 1, 1 ); _.reduce(nums, safeMult); //=> 30 • nullはデフォルト値"1"に置換される KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 62
63.
関数!fnull!の使用例(2)!:!設定オブジェクト function defaults(d) { return
function(o, k) { var val = fnull(_.identity, d[k]); return o && val(o[k]); }; } KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 63
64.
関数!defaults!の利用 function doSomething(config) { var
lookup = defaults({critical: 108}); return lookup(config, 'critical'); } doSomething({critical: 9}); //=> 9 doSomething({}); //=> 108 KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 64
65.
関数!fnull!の考察 • 危険な値(undefinedやnullなど)を気の利いたデフォルト値に 変更できる • o[k]
|| someDefault$とか書かなくても良くなる • doSomething$関数と離れた場所で引数のチェックを行える • 引数の検証ロジックをカプセル化できた KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 65
66.
4.3$すべてを結集 オブジェクトバリデータ KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 66
67.
4.3$すべてを結集オブジェクトバリデータ • 任意の基準に基いて妥当性を検証する • 流暢なものがいい •
パーツから構成したい • 発生したエラーを全て報告して欲しい KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 67
68.
関数!checker • 真偽値を返す関数を引数にとる • false"が返ってきたら、エラーメッセージを追加する •
真偽値を返す関数の"message"フィールドを探す KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 68
69.
関数!checker!の実装 function checker(/* validators
*/) { var validators = _.toArray(arguments); return function(obj) { return _.reduce(validators, function(errs, check) { if (check(obj)) return errs; else return _.chain(errs).push(check.message).value(); }, []); }; } KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 69
70.
関数!checker!の使用例 • エラーメッセージが擬似メタデータとして付与された特殊用途 の検証用関数 • 一般的な解決方法ではないが、使える KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会
70
71.
関数!checker!の使用例 var alwaysPasses =
checker(always(true), always(true)); alwaysPasses({}); // => [] var fails = always(false); fails.message = "人生における過ち"; var alwaysFails = checker(fails); alwaysFails({}); // => [ "人生における過ち" ] KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 71
72.
message!プロパティを与えることの問題 • 検証用関数を生成する度に"message"を与えるのは面倒 • もとからある"message"プロパティを削除する可能性がある •
_message"としても良いが、今度は"_message"思い出さなけ ればならない KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 72
73.
関数!validator • message"プロパティを与えることの問題を解決する高階関数 function validator(message,
fun) { var f = function(/* args */) { return fun.apply(fun, arguments); }; f['message'] = message; return f; } KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 73
74.
関数!validator!の使用例 var gonnaFail = checker(validator("ZOMG!",
always(false))); console.log(gonnaFail(100)); // => [ "ZOMG!" ] KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 74
75.
検証用関数を分離して定義する利点 • 検証用関数にわかりやすい名前を付与できる function aMap(obj)
{ reutrn _.isObject(obj); } var checkCommand = checker(validator("マップデータである必要があります", aMap)); checkCommand({}); // => [] checkCommand(42); // => [ "マップデータである必要があります" ] KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 75
76.
流暢な検証関数 • 関数を返す関数に渡す引数は、返される関数の動作を「設定」 するもの • 例:#必要なキーの単純なリストは美しく流暢 •
hasKeys('msg', 'type')とか KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 76
77.
関数!hasKeys!の実装 function hasKeys(/* 検証したいキーのリスト
*/) { var KEYS = _.toArray(arguments); var fun = function(obj) { return _.every(KEYS, function(k) { return _.has(obj, k); }); }; fun.message = cat(["Must have values for keys:"], KEYS).join(" "); return fun; } KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 77
78.
関数!hasKeys!の特徴 • 自由変数"KEYS"を確保したクロージャが妥当性検証を行う • hasKeys"関数は"fun"関数実行時の設定を行う KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会
78
79.
関数!hasKeys!の使用例 var checkCommand = checker(validator("must
be a map", aMap), hasKeys('msg', 'type')); KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 79
80.
checkCommand!の使用例 checkCommand({msg:0"blah",0type:0"display"}); //0=>0[0] checkCommand(32); //0=>0[0"マップデータである必要があります",0"Must0have0values0for0 keys:0msg0type"0] checkCommand({}); //0=>0[0"Must0have0values0for0keys:0msg0type"0] KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 80
81.
4.4#まとめ KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 81
82.
高階関数の特徴!(再掲) • 前提 • 第一級のデータ型である •
次のうち、少なくともどちらか一方を満たす • 引数として関数をとる • 関数を戻り値として返す KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 82
83.
4章"高階関数"まとめ • 関数を他の関数に渡した • iterateUntil"などを例に、関数に関数を渡したほうが良 い場合を示した •
関数が関数を返す関数を定義した • 予期しない値に対する防御策"fnull • 強力な制約関数"checker,"validator,"hasKeys KOSHIKIZAWA)Atsushi)(2015402411))第二回Topotal輪読会 83