最近、Erlang始めたので、手始めに何か適当なアルゴリズムのコードでも書いてみようかと。
まずはソートアルゴリズムの王様クイックソート。小さいのを左に集めて、大きいのを右に集めて、集めたグループ毎にそれぞれ同じよう左右に分けて…これを繰り返していけばソートできるね、というアルゴリズム。理屈は簡単なんだけど、JavaScriptで書くと…
function quickSort(array) { _quickSort(array, 0, array.length - 1); } function _quickSort(array, from, to) { if (array.length <= 1 || from >= to) { return; } var pivot = ((array[from] + array[to]) >> 1); var i = from; var j = to; while( true ) { while (pivot > array[i]) i++; while (pivot < array[j]) j--; if (i >= j) break; var tmp = array[i]; array[i] = array[j]; array[j] = tmp; i++; j--; } _quickSort(array, from, i-1); _quickSort(array, j+1, to); }
こういう一見何をやってるのかさっぱり分かんねぇコードになるわけですが、Erlangで書くと…
quicksort([]) -> []; quicksort([Head|Tail]) -> quicksort([X || X <- Tail, X < Head ]) ++ [Head] ++ quicksort([X || X <- Tail, X >= Head]).
小さいのを左に集めて、大きいのを右に集めて、繰り返し…、アルゴリズムの説明そのままのコードになる。簡単すぎ。アルゴリズムを理解するという目的であれば、関数型のコードの方が10000倍理解しやすい。
関数型っぽい書き方は、最近のJavaScriptならばサクッと書けますが…
function quickSort(array) { if (array.length <= 1) { return array; } var pivot = array.pop(); var lt = array.filter(function(a){ return a < pivot }); var ge = array.filter(function(a){ return a >= pivot }); return quickSort(lt).concat([pivot]).concat(quickSort(ge)) }
Arrayオブジェクト作りまくるので効率かなり悪そう。ただ、それ言っちゃerlangでもリスト作りまくるんだけど、気にしなくて良いのかな?