2010年6月13日日曜日

あの言語は今

あの言語は識者の助言からMIKUという名前になり、今もちょっとづつ開発が進んでいる。
とにかく、今は無名関数が使えるようになったのでいわゆるアキュムレータを返す関数が定義出来る。
すなわち、関数genacmは、「数値をとり、過去にとった数値と合計した値を返す関数」を返す関数だ。


(setf 'genacm (lambda () (set 'now 0) (lambda (inc) (set 'now (+ inc now)))))
(setf 'a1 (genacm)) ; => #
(setf 'a2 (genacm)) ; => #
(a1 1) ; => 1
(a2 2) ; => 2
(a1 3) ; => 4
(a2 4) ; => 6


パーサが前に書いたようなルールで読み取ってくれるならこう書けるはずだ。


setf[genacm {()
now = 0
{(inc) now = inc + now}]
setf[a1 genacm[]] ; => #
setf[a2 genacm[]] ; => #
a1[1] ; => 1
a2[2] ; => 2
a1[3] ; => 4
a2[4] ; => 6


例示しておいてなんだけどシンタックスは特に触れない。
注目すべきは、a1とa2は、何れもgenacmが作った関数であり、それは毎回nowに引数を加算するだけだが、nowはgenacmが呼び出される度に新たに作られる(a1とa2のnowは別物)。レキシカルスコープを持ったクロージャだ。
MIKUで定義した無名関数は、Rubyにおける無名関数と等価だ。つまり、Rubyのメソッドにそのまま渡すことが出来る。
問題は、Rubyでは無名関数を渡すときに「ブロック引数」として渡す。この特別扱いによってさも構文を拡張したかのように振る舞えるが、MIKUから渡すには新たにシンタックスを加えることになる。


ary.each{ |x| p x } # eachメソッドにブロック引数を渡している


Rubyに似せるならこんな方法があるだろう。


each[ary |x| p x]


|が出てきたら、そのリストの終わりまでを全て無名関数に変換して、ブロック引数として渡す。
一見いいような気がするが、これができるようになるということは、MIKUで定義した無名関数もブロック引数をとれるということになってしまう。そして、所詮RubyのProcオブジェクトなので、実は手を加えなくてもnew[Proc]とするだけでブロック引数を取得することが出来る。
ブロック引数は、Rubyには良いアイデアだったが、曲がりなりにもLispな言語に組み込んでも、紛らわしいだけな気がする。

とにかく、無くても死なないので、当分このまま放置。しかしこれが使えないとなると、Rubyのメソッドが叩けるとはいえないのも事実。

0 件のコメント:

コメントを投稿