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が再発見されてクロージャブームが世界観を変えたみたいに、いまマルチパラダイムって言ってるものが、なにか名前がついたひとつのパラダイムとして、将来プログラマー必須のスキルになる可能性はなきにしもあらずなんじゃないかと...。