CoffeeScriptで話すように素数しながら考えた
久しぶりに素数シリーズをやりたくなる言語に出会いました。
CoffeeScript http://jashkenas.github.com/coffee-script/
PythonとRubyとScalaとmlが混ざったような言語でプログラミングして、それをJavascriptにコンパイルします。
なんだJavascriptならかなり高級言語だし自分で書けるじゃん、と思った方はこちらをご覧あれ。
Array::fold = (f, init)-> c = init for e in this c = f(e, c) c if Array::reduce is undefined Array::reduce = (f) -> @[1..].fold(f, @[0]) sum = (a)-> a.reduce (e, c) -> e + c alert sum([1..20]) #...shows 210
これは1から20の合計をたたみ込みで求めるサンプルコードです。プロトタイプ拡張も配列のスライスも、そしてなにより関数の記述と範囲リテラルもありそうです。@でthisにアクセスしていたりします。ちなみに構文構造化はインデント厳守なPythonふうで、改行文字はRubyのように構文上有意なトークンです。関数コールの括弧省略もRubyやScalaに似ています。
これで生成された Javascript のコードがこんな感じ。
var sum; Array.prototype.fold = function(f, init) { var c, e, _i, _len; c = init; for (_i = 0, _len = this.length; _i < _len; _i++) { e = this[_i]; c = f(e, c); } return c; }; if (Array.prototype.reduce === void 0) { Array.prototype.reduce = function(f) { return this.slice(1).fold(f, this[0]); }; } sum = function(a) { return a.reduce(function(e, c) { return e + c; }); }; alert(sum([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]));
これ、先入観なしで見ると人が書いたようなムダのないjavascriptですよね。でもいちどコンパイル前のcoffeeを見てしまうと、こんなJavascriptですら低級言語に見えます。
さてじゃあ、素数を求めてみましょう。
パフォーマンスやメモ化を気にしない基本形
is_prime_number = (n)-> (m for m in [2...n] when n % m == 0).length == 0 prime_numbers_until = (lim)-> n for n in [1...lim] when is_prime_number n alert (prime_numbers_until 100 + 1)
パフォーマンスやメモ化を意識して素数を求めた場合
exists = (es, cond)-> for e in es if cond e then return true false memoize = (f)-> memo = {} return (x)-> if memo[x] is undefined then memo[x] = f(x) memo[x] is_prime_number = memoize (n)-> !exists (prime_numbers_until n), (m)-> m != 1 and n % m == 0 prime_numbers_until = (lim)-> n for n in [1...lim] when is_prime_number n alert (prime_numbers_until 100 + 1)
それぞれは以下の2つのエントリで書いたプログラムにだいたい対応します。
話すようにプログラムするPythonチュートリアル - なんたらノート 第二期
続・話すようにプログラムするPythonチュートリアル - なんたらノート 第二期
http://jashkenas.github.com/coffee-script/ の TRY COFFEESCRIPT にコードをペーストすると、本当はどれだけjavascriptを書かないといけなかったかを知って驚くと思います。
とりあえず動くプログラムを書くところまでやってみて、そのRuby並の記述性の高さに驚きです。で、そのうえそれがPythonに似た(Javascriptの)素直なランタイムで動くとなれば願ったり叶ったり。綺麗にしようとしたとき、括弧省略などのトライアンドエラーはScalaを書いているみたいな感覚でした。で、構文のすべてが式なので、文ではなくひとつの式としてイメージしないとコードの方針が立ちにくいのがOCamlっぽかったですね。このあたりの感覚が浅く広くある人だと、ほんとにすんなりいけそうです。
逆に、何かの偏った方法論に縛られてきた人には、もしかするときついかもしれません。なんだか、新しいプログラム言語はいまこういう次元にあるんだなと思うと、かつてJavaが最新の言語概念リードしていたように、javascriptが再発見されてクロージャブームが世界観を変えたみたいに、いまマルチパラダイムって言ってるものが、なにか名前がついたひとつのパラダイムとして、将来プログラマー必須のスキルになる可能性はなきにしもあらずなんじゃないかと...。