Submit Search
Upload
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 2 章
•
12 likes
•
8,658 views
YOSHIKAWA Ryota
Follow
JavaScript で学ぶ関数型プログラミングという本を読んでいる時の発表資料です
Read less
Read more
Internet
Slideshow view
Report
Share
Slideshow view
Report
Share
1 of 48
Download now
Download to read offline
Recommended
関数型プログラミング in javascript
関数型プログラミング in javascript
Ryuma Tsukano
Scalaで萌える関数型プログラミング[1.1.RC1]
Scalaで萌える関数型プログラミング[1.1.RC1]
Ra Zon
Replace Output Iterator and Extend Range JP
Replace Output Iterator and Extend Range JP
Akira Takahashi
TypeScript & 関数型講座 第3回 関数型入門
TypeScript & 関数型講座 第3回 関数型入門
gypsygypsy
What is template
What is template
Akira Takahashi
error handling using expected
error handling using expected
Akira Takahashi
関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)
啓 小笠原
Jubatusのリアルタイム分散レコメンデーション@TokyoWebmining#17
Jubatusのリアルタイム分散レコメンデーション@TokyoWebmining#17
Yuya Unno
Recommended
関数型プログラミング in javascript
関数型プログラミング in javascript
Ryuma Tsukano
Scalaで萌える関数型プログラミング[1.1.RC1]
Scalaで萌える関数型プログラミング[1.1.RC1]
Ra Zon
Replace Output Iterator and Extend Range JP
Replace Output Iterator and Extend Range JP
Akira Takahashi
TypeScript & 関数型講座 第3回 関数型入門
TypeScript & 関数型講座 第3回 関数型入門
gypsygypsy
What is template
What is template
Akira Takahashi
error handling using expected
error handling using expected
Akira Takahashi
関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)
啓 小笠原
Jubatusのリアルタイム分散レコメンデーション@TokyoWebmining#17
Jubatusのリアルタイム分散レコメンデーション@TokyoWebmining#17
Yuya Unno
RubyとJavaScriptに見る第一級関数
RubyとJavaScriptに見る第一級関数
Altech Takeno
現実(えくせる)と戦う話
現実(えくせる)と戦う話
bleis tift
普通のプログラミング言語R
普通のプログラミング言語R
Shuyo Nakatani
C#の新機能勉強会 ~ C#7、8の新機能を活用して速く安全なプログラムを書こう~
C#の新機能勉強会 ~ C#7、8の新機能を活用して速く安全なプログラムを書こう~
Fujio Kojima
Python基礎その1
Python基礎その1
大貴 末廣
Linqことはじめ
Linqことはじめ
Shoichi Yasui
Clojure programming-chapter-2
Clojure programming-chapter-2
Masao Kato
Java x Groovy: improve your java development life
Java x Groovy: improve your java development life
Uehara Junji
Python基礎その2
Python基礎その2
大貴 末廣
オブジェクト指向入門7
オブジェクト指向入門7
Kenta Hattori
分類問題 - 機械学習ライブラリ scikit-learn の活用
分類問題 - 機械学習ライブラリ scikit-learn の活用
y-uti
TaPL読書会 #9 ~ §14 Exception
TaPL読書会 #9 ~ §14 Exception
Akihiro Miyashita
科学技術計算関連Pythonパッケージの概要
科学技術計算関連Pythonパッケージの概要
Toshihiro Kamishima
DS Exercise Course 2
DS Exercise Course 2
大貴 末廣
Introduction to lambda calculation
Introduction to lambda calculation
relipmoc101
Python 機械学習プログラミング データ分析演習編
Python 機械学習プログラミング データ分析演習編
Etsuji Nakai
乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-
乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-
Takuya Akiba
Swift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsap
Swift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsap
Tomohiro Kumagai
[第2版]Python機械学習プログラミング 第8章
[第2版]Python機械学習プログラミング 第8章
Haruki Eguchi
Pythonによる機械学習入門〜基礎からDeep Learningまで〜
Pythonによる機械学習入門〜基礎からDeep Learningまで〜
Yasutomo Kawanishi
Jbatch実践入門 #jdt2015
Jbatch実践入門 #jdt2015
Norito Agetsuma
JavaScript入門
JavaScript入門
Ryo Maruyama
More Related Content
What's hot
RubyとJavaScriptに見る第一級関数
RubyとJavaScriptに見る第一級関数
Altech Takeno
現実(えくせる)と戦う話
現実(えくせる)と戦う話
bleis tift
普通のプログラミング言語R
普通のプログラミング言語R
Shuyo Nakatani
C#の新機能勉強会 ~ C#7、8の新機能を活用して速く安全なプログラムを書こう~
C#の新機能勉強会 ~ C#7、8の新機能を活用して速く安全なプログラムを書こう~
Fujio Kojima
Python基礎その1
Python基礎その1
大貴 末廣
Linqことはじめ
Linqことはじめ
Shoichi Yasui
Clojure programming-chapter-2
Clojure programming-chapter-2
Masao Kato
Java x Groovy: improve your java development life
Java x Groovy: improve your java development life
Uehara Junji
Python基礎その2
Python基礎その2
大貴 末廣
オブジェクト指向入門7
オブジェクト指向入門7
Kenta Hattori
分類問題 - 機械学習ライブラリ scikit-learn の活用
分類問題 - 機械学習ライブラリ scikit-learn の活用
y-uti
TaPL読書会 #9 ~ §14 Exception
TaPL読書会 #9 ~ §14 Exception
Akihiro Miyashita
科学技術計算関連Pythonパッケージの概要
科学技術計算関連Pythonパッケージの概要
Toshihiro Kamishima
DS Exercise Course 2
DS Exercise Course 2
大貴 末廣
Introduction to lambda calculation
Introduction to lambda calculation
relipmoc101
Python 機械学習プログラミング データ分析演習編
Python 機械学習プログラミング データ分析演習編
Etsuji Nakai
乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-
乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-
Takuya Akiba
Swift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsap
Swift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsap
Tomohiro Kumagai
[第2版]Python機械学習プログラミング 第8章
[第2版]Python機械学習プログラミング 第8章
Haruki Eguchi
Pythonによる機械学習入門〜基礎からDeep Learningまで〜
Pythonによる機械学習入門〜基礎からDeep Learningまで〜
Yasutomo Kawanishi
What's hot
(20)
RubyとJavaScriptに見る第一級関数
RubyとJavaScriptに見る第一級関数
現実(えくせる)と戦う話
現実(えくせる)と戦う話
普通のプログラミング言語R
普通のプログラミング言語R
C#の新機能勉強会 ~ C#7、8の新機能を活用して速く安全なプログラムを書こう~
C#の新機能勉強会 ~ C#7、8の新機能を活用して速く安全なプログラムを書こう~
Python基礎その1
Python基礎その1
Linqことはじめ
Linqことはじめ
Clojure programming-chapter-2
Clojure programming-chapter-2
Java x Groovy: improve your java development life
Java x Groovy: improve your java development life
Python基礎その2
Python基礎その2
オブジェクト指向入門7
オブジェクト指向入門7
分類問題 - 機械学習ライブラリ scikit-learn の活用
分類問題 - 機械学習ライブラリ scikit-learn の活用
TaPL読書会 #9 ~ §14 Exception
TaPL読書会 #9 ~ §14 Exception
科学技術計算関連Pythonパッケージの概要
科学技術計算関連Pythonパッケージの概要
DS Exercise Course 2
DS Exercise Course 2
Introduction to lambda calculation
Introduction to lambda calculation
Python 機械学習プログラミング データ分析演習編
Python 機械学習プログラミング データ分析演習編
乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-
乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-
Swift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsap
Swift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsap
[第2版]Python機械学習プログラミング 第8章
[第2版]Python機械学習プログラミング 第8章
Pythonによる機械学習入門〜基礎からDeep Learningまで〜
Pythonによる機械学習入門〜基礎からDeep Learningまで〜
Similar to 【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 2 章
Jbatch実践入門 #jdt2015
Jbatch実践入門 #jdt2015
Norito Agetsuma
JavaScript入門
JavaScript入門
Ryo Maruyama
仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)
仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)
Hiroaki KOBAYASHI
Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]
Ra Zon
Swiftによる関数型プログラミング超入門
Swiftによる関数型プログラミング超入門
Hisakuni Fujimoto
Rあんなときこんなとき(tokyo r#12)
Rあんなときこんなとき(tokyo r#12)
Shintaro Fukushima
LastaFluteでKotlinをはじめよう
LastaFluteでKotlinをはじめよう
Shinsuke Sugaya
たのしい関数型
たのしい関数型
Shinichi Kozake
ATN No.2 Scala事始め
ATN No.2 Scala事始め
AdvancedTechNight
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 4 章
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 4 章
Last Arrow
Dotnetconf2017
Dotnetconf2017
Yoshiyuki Taniguchi
20160215 04 java ee7徹底入門 jbatch
20160215 04 java ee7徹底入門 jbatch
Jun Inose
jvmlang.daitokai 1.0.0 MinCamlJを作ってみた
jvmlang.daitokai 1.0.0 MinCamlJを作ってみた
Kazuyoshi Kamitsukasa
JavaScript 講習会 #1
JavaScript 講習会 #1
Susisu
知って得するWebで便利なpostgre sqlの3つの機能
知って得するWebで便利なpostgre sqlの3つの機能
Soudai Sone
データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回
Naoyuki Yamada
ちょっと詳しくJavaScript 第4回【スコープとクロージャ】
ちょっと詳しくJavaScript 第4回【スコープとクロージャ】
株式会社ランチェスター
ECMAScript6による関数型プログラミング
ECMAScript6による関数型プログラミング
TanUkkii
第一回Data mining勉強会 -第二章
第一回Data mining勉強会 -第二章
Tomonobu_Hirano
C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)
信之 岩永
Similar to 【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 2 章
(20)
Jbatch実践入門 #jdt2015
Jbatch実践入門 #jdt2015
JavaScript入門
JavaScript入門
仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)
仕事の手離れを良くする手段としての、静的検査のあるテンプレートエンジン (YATT::Lite talk at 2014 テンプレートエンジンNight)
Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]
Swiftによる関数型プログラミング超入門
Swiftによる関数型プログラミング超入門
Rあんなときこんなとき(tokyo r#12)
Rあんなときこんなとき(tokyo r#12)
LastaFluteでKotlinをはじめよう
LastaFluteでKotlinをはじめよう
たのしい関数型
たのしい関数型
ATN No.2 Scala事始め
ATN No.2 Scala事始め
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 4 章
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 4 章
Dotnetconf2017
Dotnetconf2017
20160215 04 java ee7徹底入門 jbatch
20160215 04 java ee7徹底入門 jbatch
jvmlang.daitokai 1.0.0 MinCamlJを作ってみた
jvmlang.daitokai 1.0.0 MinCamlJを作ってみた
JavaScript 講習会 #1
JavaScript 講習会 #1
知って得するWebで便利なpostgre sqlの3つの機能
知って得するWebで便利なpostgre sqlの3つの機能
データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回
ちょっと詳しくJavaScript 第4回【スコープとクロージャ】
ちょっと詳しくJavaScript 第4回【スコープとクロージャ】
ECMAScript6による関数型プログラミング
ECMAScript6による関数型プログラミング
第一回Data mining勉強会 -第二章
第一回Data mining勉強会 -第二章
C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 2 章
1.
第一級関数と作用的プログラミング JavaScript*で学ぶ関数型プログラミング*2*章 YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 1
2.
内容 • 第一級要素としての関数 • JavaScript+のプログラミングパラダイムについて •
作用的プログラミング・コレクション中心プログラミング • データ思考プログラミング • テーブルのようなデータの取り扱い YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 2
3.
第一級要素としての関数 YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 3
4.
第一級関数 • JavaScript+の第一級要素+:+数値・文字列+...+関数 • つまり関数と数値や文字列は同じ性質を持つ •
変数に代入可能 • 任意のタイミングで生成可能 • 関数の引数・戻り値になる+3 3 "ここでは""関数型""を言語に対する形容詞として使っていない YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 4
5.
// 変数・配列・オブジェクトのフィールドに代入可能 var f
= function() { return 42 }, a = [42, function() { return 42 }], o = {n: 42, f: function() { return 42 }}; // 任意のタイミングで生成可能 42 + (function(){ return 42 })(); //=> 84 // 引数・返り値に取ることが可能 (恒等関数での例) function identity(x) { return x }; identity(function() { return 42 }); //=> function() YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 5
6.
閑話休題:"JavaScript"は関数型言語か?"1 • そもそも""関数型言語""の基準は? • 関数が第一級要素? •
参照透過性? • 副作用の隠 ? • 型推論? 1 "h$p://www.slideshare.net/ksknac/120901fp9key"(24"ページ) YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 6
7.
そもそも関数型とは?!2 • 以下のようなプログラミング"パラダイム"に対する形容"3 • プログラムのほとんどが関数であるような書き方 •
非関数や副作用の影響を可能な限り小さくする • 使用する言語に関係なく実現が可能 3 "ここでは""関数型""を言語に対する形容詞として使っていない 2 "h$p://www.slideshare.net/ksknac/120901fp9key"(25"ページ) YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 7
8.
改めて:"JavaScript"は関数型言語か? • 関数型(パラダイムのプログラミングをしやすい)言語か? • JavaScript-では関数が第一級要素となっている •
関数型スタイルでのプログラミングはしやすい • その他の関数型の機能は言語としてサポートはされていない →書き手の配慮により関数型スタイルで書くことが可能な言語- 4 ""変数再代入をしない""とか""関数は必ず値を返し、副作用がないようにする""とか。 YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 8
9.
JavaScript*の* *プログラミングパラダイム YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 9
10.
・!命令型プログラミング ・!関数型プログラミング ・!プロトタイプベースオブジェクト指向 ・!メタプログラミング 5 "よく見られるものを示した。ES6"からクラスベースオブジェクト指向も見られるようになるかも。 YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 10
11.
命令型プログラミング • 実行フローをほぼそのまま書き下す • プログラムの実行状態を直接操作・参照する •
対となるパラダイムは"宣言型プログラミング • 関数型や論理型は宣言型プログラミングに属する • C"言語・BASIC・PASCAL"等はこのパラダイムを取る事が多い YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 11
12.
例)"99"本のビール • 99#から開始し、1#ずつ引いていき繰り返す • 現在の数を#X#として、次のように歌う •
X#本のビールが残ってる#=>#X#本のビール • ひとつ取って、隣に回せ#=>#X(1#本のビールが残ってる • X=1#の時は最後の部分で#もうビールは残ってない#と歌う。 YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 12
13.
// 命令型プログラミング var lyrics
= []; for (var bottles = 99; bottles > 0; bottles--) { lyrics.push(bottles + " 本のビールが残ってる"); lyrics.push(bottles + " 本のビール"); lyrics.push("ひとつ取って、隣に回せ"); if (bottles > 1) { lyrics.push((bottles - 1) + "本のビールが残ってる"); } else { lyrics.push("もうビールは残ってない"); } } // この後に 80∼50 本のビールの歌を歌わせたかったら...? // この部分のテストが書きたくなったら...? YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 13
14.
// 関数型スタイルへのパラダイムシフト // "n
本目のビールの歌詞を生成する" 機能を関数へと分割 function lyricSegment(n) { return _.chain([]) // メソッドチェイン記法 .push(n + " 本のビールが残ってる") .push(n + " 本のビール") .push("ひとつ取って、隣に回せ") .tap(function(lyrics) { // 渡ってきたオブジェクトに関数を適用しオブジェクトを返す if (n > 1) lyrics.push((n - 1) + " 本のビールが残ってる"); else lyrics.push("もうビールは残ってない"); }) .value(); // 値を返す } YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 14
15.
// 関数の繋ぎあわせ function song(start,
end, lyricGen) { return _.reduce(_.range(start,end,-1), // 値を返す function(acc,n) { return acc.concat(lyricGen(n)); // 値を返す }, []); } song(99, 0, lyricSegment) // => ["99 本のビールが残ってる", "99 本のビール", "ひとつ取って、隣に回せ", ... ] // song(80, 50, lyricSegment) で 80∼50 本のビールの歌が歌える // 正しく値が返って来ているかのテストも書きやすそう // 歌詞生成部だけのテストも書けそう YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 15
16.
命令型と関数型 • 前述の例のように、ルールを守って処理を細かく関数に分ける • 命令型では"99"本・同じ歌詞でしか動かせなかった •
関数型では関数として定義することにより抽象的に • 99"本のビール,"30"本のビール..."は"song"関数ですぐ作れる 6 "英語で歌わせたければ"enLyricSegment"のような関数を用意し"song(99,"0,"enlyricsegment)"のようにすればよい YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 16
17.
何が良いと感じたか • 機能別に分けることにより • 変更に強いプログラムが作れる •
再利用性が高く同じようなコードを何度も書かなくて良い • 機能毎のテストが書きやすくなる • 参照等価にするとここが∼みたいな話は色々あるけど...#7 7 "とりあえずここまでの例で読み取れることのみの感想です YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 17
18.
プロトタイプベースオブジェクト指向 • JavaScript+のオブジェクト指向はプロトタイプベース • 既存のオブジェクトをプロトタイプとして使用する+8 •
クラス指向のオブジェクト指向に対してローレベルで動作する • 柔軟性はあるが罠も多い 8 "以降「関数」は単独で存在する関数、「メソッド」はオブジェクトのコンテキストに生成された関数を指す YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 18
19.
罠 // オブジェクトのフィールド値に関数が存在できる var a
= {name: "a", f: function(){return this}}; // this は a 自身を指す。計画通り。 a.f() // => {name: "a", f: ...} var bObj = {name: "b", f: function(){return this}}, var bFun = bObj.f; // !! this は bObj を指さない !! bFun から見た this を指す !! bFun() // => グローバルオブジェクト (window など) 8 "以降「関数」は単独で存在する関数、「メソッド」はオブジェクトのコンテキストに生成された関数を指す YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 19
20.
メタプログラミング • ソースコードを生成するようなプログラムを書くスタイル • 本書では、以下のような例が紹介されている"9 function
Point2D(x, y) { this._x = x; this._y = y; } function Point3D(x, y, z) { Point2D.call(this, x, y); this._z = z; } new Point3D(10, -1, 100); //=> {_x: 10, _y: -1, _z: 100} • 本書ではほぼ取り扱わないので詳細は省略する 9 "この例があまりメタプログラミングっぽく見えないのは"JavaScript"のデータ構造とプログラム構造が近いから? YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 20
21.
作用的プログラミング! !コレクション中心プログラミング YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 21
22.
作用的プログラミング • 関数"f: A()"と"f:
B()"を次のように使用するプログラミング • B"を呼び出すことで"A"を実行させる"10 • B(element, A()) • "作用的"という言葉はコンテキストによって異なる意味を持つ • もう使わないけど意味だけは知っておいてね 10 #と、本書では定義してあるのでこのスライドでもそう定義します。 YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 22
23.
作用的プログラミングの例 var nums =
[1,2,3,4,5]; function doubleAll(array) { return _.map(array, function(n) { return n*2 }); } doubleAll(nums); //=> [2, 4, 6, 8, 10] // --------------------- function average(array) { var sum = _.reduce(array, function(a, b) { return a+b }); return sum / _.size(array); } average(nums); //=> 3 // --------------------- function onlyEven(array) { return _.filter(array, function(n) { return (n%2) === 0; }); } onlyEven(nums); //=> [2, 4] YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 23
24.
コレクション中心プログラミング • 関数型プログラミング • コレクションに入った多数の値に同じ処理をしやすい •
[1, 2, 3, 4, 5]"や"{a: 1, b: 2}"... • 本書はこの考え方に則りデータ構造を有効活用する方法を推進 • It#is#be(er#to#have#100#func4ons#operate#on#one#data#structure#than# 10#func4ons#on#10#data#structures.#88#Alan#Perlis YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 24
25.
コレクション中心プログラミングの例 _.map({a: 1, b:
2}, _.identity); //=> [1,2] // --------------------- _.map({a: 1, b: 2}, function(v,k) { return [k,v]; }); //=> [['a', 1], ['b', 2]] // --------------------- _.map({a: 1, b: 2}, function(v,k,coll) { return [k, v, _.keys(coll)]; }); //=> [['a', 1, ['a', 'b']], ['b', 2, ['a', 'b']]] YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 25
26.
作用的プログラミングのその他の例 // ReduceRight var nums
= [100,2,25]; function div(x,y) { return x/y }; _.reduce(nums, div); //=> 2 _.reduceRight(nums, div); //=> 0.125 // allOf, anyOf; reduce でも同じように記述できる function allOf(/* funs */) { return _.reduceRight(arguments, function(truth, f) { return truth && f(); }, true); } function anyOf(/* funs */) { return _.reduceRight(arguments, function(truth, f) { return truth || f(); }, false); } YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 26
27.
// ReduceRight // allOf,
anyOf の使用例 function T() { return true } function F() { return false } allOf(); //=> true allOf(T, T); //=> true allOf(T, T, T , T , F); //=> false anyOf(T, T, F); //=> true anyOf(F, F, F, F); //=> false anyOf(); //=> false • reduce/reduceRight-は演算が結合的でない時に差が発生 • 遅延評価の言語ではもっと大きな違いがある YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 27
28.
// find, reject,
filter, all, any // find: コレクションとプレディケートを取り真となる要素を返す _.find(['a', 'b', 3, 'd'], _.isNumber); //=> 3 // find の逆の動作; underscore.js は _.isNumber のようなプレディケート関数を多数用意している _.reject(['a', 'b', 3, 'd'], _.isNumber); //=> ['a', 'b', 'd'] // 真偽を判定させる関数 complement function complement(pred) { return function() { return !pred.apply(null, _.toArray(arguments)); }; } // _.reject と同じ動作 _.filter(['a', 'b', 3, 'd'], complement(_.isNumber)); //=> ['a', 'b', 'd'] // all: 要素のすべてが true の時 true; any: 要素の1つでも true なら true _.all([1, 2, 3, 4], _.isNumber); //=> true _.any([1, 2, 'c', 4], _.isString); //=> true YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 28
29.
// sortBy, countBy,
groupBy var people = [{name: "Rick", age: 30}, {name: "Jaka", age: 24}]; // コレクションと関数を受け取り関数の基準に応じて並べ替えたコレクションを返す _.sortBy(people, function(p) { return p.age }); //=> [{name: "Jaka", age: 24}, {name: "Rick", age: 30}] var albums = [{title: "Sabbath Bloody Sabbath", genre: "Metal"}, {title: "Scientist", genre: "Dub"}, {title: "Undertow", genre: "Metal"}]; // 受け取った関数が返す値をキーとして、その値が等しいオブジェクトを配列に入れて返す _.groupBy(albums, function(a) { return a.genre }); //=> {Metal:[{title:"Sabbath Bloody Sabbath", genre:"Metal"}, // {title:"Undertow", genre:"Metal"}], // Dub: [{title:"Scientist", genre:"Dub"}]} // _.groupBy と同じ動作をするが、キーに対応する値が配列の長さになっている _.countBy(albums, function(a) { return a.genre }); //=> {Metal: 2, Dub: 1} YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 29
30.
作用的関数の定義 // 作用的ではない関数達 // 幾つかの配列を結合する関数 function
cat() { var head = _.first(arguments); if (existy(head)) return head.concat.apply(head, _.rest(arguments)); else return []; } cat([1,2,3], [4,5], [6,7,8]); //=> [1, 2, 3, 4, 5, 6, 7, 8] // 要素と配列を引数に取り配列の前に要素を挿入する関数 // これも作用的な関数ではない function construct(head, tail) { return cat([head], _.toArray(tail)); } construct(42, [1,2,3]); //=> [42, 1, 2, 3] YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 30
31.
// 作用的な関数 mapcat //
_.map を使用し fun を受け取り渡されたコレクションの要素全てに対して fun を実行する // その後 _.map から返された全ての要素を結合する function mapcat(fun, coll) { return cat.apply(null, _.map(coll, fun)); } mapcat(function(e) { return construct(e, [","]); }, [1,2,3]); // => [1, ",", 2, ",", 3, ","] // construct は要素を配列の先頭に挿入する関数 // 内部的には: cat.apply(null, [[1, ","], [2, ","], [3, ","]]) YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 31
32.
function butLast(coll) { return
_.toArray(coll).slice(0, -1); } function interpose (inter, coll) { return butLast(mapcat(function(e) { return construct(e, [inter]); }, coll)); } interpose(",", [1,2,3]); //=> [1, ",", 2, ",", 3] // ([1, 2, 3] => [1, ",", 2, ",", 3, ","] => [1, "," 2, ",", 3]) YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 32
33.
作用的関数 • 低レベルの関数によって組み立てられた個別の機能を組合わせ • 複数の関数が作用的に呼び出される •
それぞれの関数がデータを処理し最後の解に至る • 関数型プログラミングの重要な切り口 • 今後本書ではこのようなパターンが多数登場 YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 33
34.
データ思考 • JavaScript+におけるオブジェクト型は非常に強力 • ポリモーフィックディスパッチ/単純な連想データストア •
データストアとして扱う関数は+JavaScript+自体にはほぼ無い • Underscore+が有用なツールを提供し、オブジェクト等に特化 しない一意な定義が可能+11 11 "「情報の断片ごとに定義された、マイクロ言語のようなもの」(Hickey"2011)"から逃れられる YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 34
35.
// keys/values は
key/value を返す(当然) var zombie = {name: "Bub", film: "Day of the Dead"}; _.keys(zombie); //=> ["name", "film"] _.values(zombie); //=> ["Bub", "Day of the Dead"] // pluck は 指定したキーの要素を全て返す(無い時は undefined) _.pluck([{title: "Chthon", author: "Anthony"}, {title: "Grendel", author: "Gardner"}, {title: "After Dark"}], 'author'); //=> ["Anthony", "Gardner", undefined] // pairs は {a: b, c: d} を [[a, b], [c, d]] とする _.pairs(zombie); //=> [["name", "Bub"], ["film", "Day of the Dead"]] YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 35
36.
// シーケンシャルな処理を行い、_.object でオブジェクトを再構成する例 _.object(_.map(_.pairs(zombie),
function(pair) { return [pair[0].toUpperCase(), pair[1]]; })); //=> {FILM: "Day of the Dead", NAME: "Bub"}; // _.invert はキーと値を入れ替える _.invert(zombie); //=> {"Bub": "name", "Day of the Dead": "film"} // JavaScript のキーは必ず文字列になる _.keys(_.invert({a: 138, b: 9})); //=> ['9', '138'] YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 36
37.
// _.defaults は指定したキーが存在しない場合デフォルト値として追加する _.pluck(_.map([{title:
"Chthon", author: "Anthony"}, {title: "Grendel", author: "Gardner"}, {title: "After Dark"}], function(obj) { return _.defaults(obj, {author: "Unknown"}) }), 'author'); //=> ["Anthony", "Gardner", "Unknown"] // _.pick, _.omit は引数によりオブジェクトの内容をフィルタする (非破壊的操作) var person = {name: "Romy", token: "j3983ij", password: "tigress"}; var info = _.omit(person, 'token', 'password'); info; //=> {name: "Romy"} var creds = _.pick(person, 'token', 'password'); //=> {password: "tigress", token: "j3983ij"}; YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 37
38.
// findWhere, where
は 2 番目の引数の条件にマッチするオブジェクトを // 1 番目の引数から探してくる var library = [{title: "SICP", isbn: "0262010771", ed: 1}, {title: "SICP", isbn: "0262510871", ed: 2}, {title: "Joy of Clojure", isbn: "1935182641", ed: 1}]; // findWhere は最初にマッチしたものだけが返る _.findWhere(library, {title: "SICP", ed: 2}); //=> {title: "SICP", isbn: "0262510871", ed: 2} // where はマッチした全ての要素が配列で返る _.where(library, {title: "SICP"}); //=> [{title: "SICP", isbn: "0262010771", ed: 1}, // {title: "SICP", isbn: "0262510871", ed: 2}] YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 38
39.
テーブルのようなデータ • 前項で示した"library"のようなデータの取り扱い • JavaScript"のオブジェクトの配列をデータテーブルとして見る •
行が"JavaScript"オブジェクト/セルがオブジェクトのキー値ペア YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 39
40.
テーブルのようなデータ!2 • タイトルを抜き出したテーブル SELECT title
FROM library; _.pluck(library, 'title'); // ここまでで習った JavaScript での同等の表現 // 但し、オブジェクトから配列に変換されており、型が壊れている ... YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 40
41.
// _.pick を使用しテーブルデータの抽象型を維持する function
project(table, keys) { return _.map(table, function(obj) { return _.pick.apply(null, construct(obj, keys)); }); }; var editionResults = project(library, ['title', 'isbn']); // => [{isbn: "0262010771", title: "SICP"}, // {isbn: "0262510871", title: "SICP"}, // {isbn: "1935182641", title: "Joy of Clojure"}]; // (_.pick.apply(null, [{...}, 'title', 'isbn']) が要素ごとに実行される) // データ構造を維持したまま値を返すため、更に project を適用可能 var isbnResults = project(editionResults, ['isbn']); //=> [{isbn: "0262010771"}, {isbn: "0262510871"}, {isbn: "1935182641"}] _.pluck(isbnResults, 'isbn'); // 欲しいデータだけを取得する //=> ["0262010771", "0262510871", "1935182641"] YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 41
42.
データの抽出 • 上記で見たようなデータ構造を破壊して必要な値を得る操作 • あるモジュールから別のモジュールへデータを「引渡す」操作 •
関数型スタイルではデータの内容/変換/フォーマットを考える YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 42
43.
抽象テーブル型 • SQL%では%AS%句を使ってカラムに別名を与えることが可能 SELECT ed
AS edition FROM library; /* 下のテーブルのような出力 */ • 次に、JavaScript+で+as+や+where+を実装してみる YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 43
44.
// マップデータを指定した通りにリネームする関数 function rename(obj,
newNames) { return _.reduce(newNames, function(o, nu, old) { if (_.has(obj, old)) { o[nu] = obj[old]; return o; } else return o; }, _.omit.apply(null, construct(obj, _.keys(newNames)))); }; rename({a: 1, b: 2}, {'a': 'AAA'}); //=> {AAA: 1, b: 2} // オブジェクトの再構成に _.reduce を使用している // これによってマップデータらしさを維持しつつキーの名前を変換している YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 44
45.
// rename 関数を使用し実装した
as 関数 function as(table, newNames) { return _.map(table, function(obj) { return rename(obj, newNames); }); }; as(library, {ed: 'edition'}); //=> [{title: "SICP", isbn: "0262010771", edition: 1}, // {title: "SICP", isbn: "0262510871", edition: 2}, // {title: "Joy of Clojure", isbn: "1935182641", edition: 1}] // as はテーブルデータ型を返すので project, as を同時に適用可能 project(as(library, {ed: 'edition'}), ['edition']); //=> [{edition: 1}, {edition: 2}, {edition: 1}]; YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 45
46.
// プレディケートを受け取りそれぞれのオブジェクトに対して適用する関数 function restrict(table,
pred) { return _.reduce(table, function(newTable, obj) { if (truthy(pred(obj))) return newTable; else return _.without(newTable, obj); }, table); }; restrict(library, function(book) { return book.ed > 1; }); //=> [{title: "SICP", isbn: "0262510871", ed: 2}] YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 46
47.
SELECT title, isbn,
edition FROM ( SELECT ed AS edition FROM library ) EDS WHERE edition > 1; /* SQL での例 */ // 上記の SQL と同等な JavaScript を使った例 restrict( project( as(library, {ed: 'edition'}), ['title', 'isbn', 'edition']), function(book) { return book.edition > 1; }); //=> [{title: "SICP", isbn: "0262510871", edition: 2},] // restrict, as, project は同じテーブル抽象型(オブジェクトの配列)に対して動作する // これがデータ思考プログラミング YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 47
48.
まとめ • JavaScript+の関数型(スタイルで書ける)言語としての側面 • 第一級関数/手続き型から関数型スタイルへの書き換え •
JavaScript+の様々なプログラミングパラダイムについて • 作用的プログラミングについて • コレクション中心プログラミング/テーブル様データの取扱い YOSHIKAWA)Ryota)(2015/1/22|2015/2/11))第一回/第二回)Topotal)輪読会 48
Download now