めちゃくちゃわかりやすいFunctional JavaScriptチュートリアル
JavaScriptで学ぶ関数型プログラミング
posted with amazlet at 14.08.05
Michael Fogus
オライリージャパン
売り上げランキング: 209,036
オライリージャパン
売り上げランキング: 209,036
夏ですね。暑いですね。
私の部屋のクーラーは数年前から故障したままなので、家に帰ってから何もやりたくありません。というかパソコン使うとサウナみたいになるしぶち壊れそう。
なので、本日も小ネタです。
何となくネットをさまよって居たらJavaScriptを関数型のパラダイムで記述する、ひじょうにわかり易いチュートリアル記事を発見しました。
Functional JavaScript for crawling the Web | Code | Nicolas Perriault
テーブルからデータを取得する一連の処理を、一段階づつFanctionalなコードへと書き替えていくチュートリアルです。
コードを書き替えていく過程が分かり易く提示されているので、ぶっちゃけ英語が読めなくてもサンプルコードを追っていくだけで理解できる素晴らしいチュートリアルです。
ただ、ES6の文法で書かれているので(アロー関数とか)そこだけ、ちょっとなれないと読み辛いかもしれません。
Functional JavaScriptingに興味ある方にお勧めです。
サンプル
ES5で書いてみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
/* *Functional JavaScript for crawling the Web *https://nicolas.perriault.net/code/2013/functional-javascript-for-crawling-the-web/ * */ /*************************************************** * * Helper Fantion * *************************************************/ //デバッグ用 function logs(){ console.log(arguments); return arguments; } //domから要素を取得 function nodes(sel, root){ return (root || document).querySelectorAll(sel); } //nodesの中から特定の要素を見つけ出す function finder(selector) { return function(root) { return nodes(selector, root); } } //与えられた関数を配列のすべての要素に対して適用 function map(fn, iterable){ return [].map.call(iterable, fn) } //オブジェクトからプロパティを指定して取得 function prop(name){ return function(object){ return object[name]; } } //functionを順番に実行 function sequence() { var fns = Array.prototype.slice.call(arguments); return fns.reduce(function(comp, fn) { return function(){ var args = Array.prototype.slice.call(arguments); return comp(fn.apply(null, args)) }; }); }; //隣り合う 2 つの配列要素に対して(左から右へ)同時に関数を適用 function reduce(fn, init, iterable){ return [].reduce.call(iterable, fn, init) } //関数合成 function compose(){ var fns = Array.prototype.slice.call(arguments); return sequence.apply(null, fns.reverse()); } //カリー化 function curry( orig_func ) { var ap = Array.prototype; var args = arguments; function fn() { ap.push.apply( fn.args, arguments ); return fn.args.length < orig_func.length ? fn : orig_func.apply( this, fn.args ); }; return function() { fn.args = ap.slice.call( args, 1 ); return fn.apply( this, arguments ); }; }; //部分適用 function partial( orig_func ) { var aps = Array.prototype.slice, args = aps.call( arguments, 1 ); return function() { return orig_func.apply( this, args.concat( aps.call( arguments ) ) ); }; }; /************************************************** * * 以下、main * *************************************************/ //テーブルからrow要素を取得 var rows = nodes("tbody tr"); //rowsからtdを取得 var findCells = finder("td"); //セルのテキストを取得 var getText = prop("textContent"); var getFirst = prop(0); var getSecond = prop(1); var getThird = prop(2); /******************************* * テーブルの1行目(国名)を取得 *******************************/ console.log( "first-ColumnList", map(compose(findCells, getFirst, getText), rows) ) /******************************* * 途中の処理にlogsを挟んでデバッグ *******************************/ console.log( "debug", map(compose(findCells, getFirst, logs, getText), rows) ) /******************************* * 人口の合計を取得 *******************************/ var sum = function(a, b) { return a + b; } var populations = map(compose(findCells, getSecond, getText, parseFloat), rows); console.log("sum-populations", reduce(sum, 0, populations)); /******************************* * データをオブジェクトに変換 *******************************/ var asObject = function(data){ return { name:getFirst(data), population: parseFloat(getSecond(data)), gnp:parseFloat(getThird(data)) } }; var getTexts = partial(map, getText); //getText関数をmap関数に部分適用して、arrayにgetTextを使えるようにする console.log("toObject", map(compose(findCells, getTexts, asObject), rows )) |
See the Pen Functional JavaScript for crawling the Web by shimizu masayuki (@shimizu) on CodePen.