PythonでSchemeを作りました

1000人スピーカカンファレンスの二次会の飲み会会場を追い出された後、なぜかサイボウズラボに戻って三次会。

なぜかyukobaがSchemeを作り始め、amachangも「作る」と言い出した!「どうせだからハッカソンにしよう」って話が!いや、そんなことしだしたら帰れないし!ああっ!でも今書かなければ一生書かないかもしれないっ!

というわけで書いたのがこちら。
どう書く?org 5414 にしお: 飲み会の後5時間で作ったものなのでかなり...(Schemeもどきの実装) - 投稿の詳細

残りの二人の書いたものはこちら。
Scheme on JavaScript 作りました - yukobaの日記
わーい \(^o^)/ Scheme もどきを JS で書いたよー! - IT戦記

          • -

せっかくなのでハッカソンの雰囲気を少しでも伝えられるように書いてみる↓
以下オフラインの発言は「」、Lingrでの発言は>

http://www.lingr.com/room/1000speakers/archives/2008/01/20#msg-23892898
nishio「テストケースLingrに貼ってよ」
yukoba

( begin ( define sum3 ( lambda ( a b c ) ( + a b c ) ) ) ( sum3 10 20 30 ) )
( sum3 10 20 30 ) 

yukoba「defineってグローバルスコープに書くの?」
amachang

( begin ( define sum3 ( lambda ( a b c ) ( + a b c ) ) ) ( sum3 10 20 30 ) ) (sum3 10)
これができたら sum3 はグロバル
(begin (define sum3 (lambda (a b c) (+ a b c)))) (sum3 1 2 3)

nishio

gosh> ((lambda () (define foofoo 1)))
#<undef>
gosh> foofoo
*** ERROR: unbound variable: foofoo
これで、foofooがグローバルで参照できないからdefineはグローバルでない

nishio > わわわー、Schemeってdefineをdefineできるのか

誰か「トークナイザってどうなってるの」
http://www.lingr.com/room/1000speakers/archives/2008/01/20#msg-23899091

yukoba「次の目標はdefineで関数定義」
http://www.lingr.com/room/1000speakers/archives/2008/01/20#msg-23901302

amachang不定長の引数を取る関数ってどうやるんだろう」
http://www.lingr.com/room/1000speakers/archives/2008/01/20#msg-23903357

yukoba「次の目標はlet」
http://www.lingr.com/room/1000speakers/archives/2008/01/20#msg-23905318

nishio「ぎゃー、lambdaがうまく動かないと思ったらトークナイザにバグがあったw」
この後遅れに遅れていた僕がやっとlambdaが動くようになる

letをlambdaへの変換で実装しようとしてつまづいているyukobaを横目に僕が先にletを実装

コードレビュー。amachang「これクロージャできてないんじゃない?」nishio「できてなさげ…テストコード書いてかいて」

amachang

これで、 5 が変えればおk
(define cl (let ((bar 5)) (lambda () bar)))
(define bar 6)
(cl)

nishio「6返ったしょぼーん」
yukoba「undefになる!なぜ?!」
nishio「それ複数の式がある場合に暗黙のbeginになってなくでdefineだけ実行されてるんじゃね?」

この後おなかがすいたのでご飯を食べに外に行く。店が一つも開いてない!!紆余曲折の末すきやを発見。
すきやで話していてそもそも僕の実装はフィボナッチどころじゃないことがばれるw
amachangとyukobaはタクシーで帰る。僕だけ逆方向&半蔵門線の逆の端っこだからめっちゃ遠い!
ラボに戻ってスコープの挙動を確認。

nishio

gosh> (define f (let ((x 1)) (lambda () y)))
f
gosh> (let ((y 2)) (f))
*** ERROR: unbound variable: y
へーこうなるのかぁ

つっこまれたところを直す。lambdaがスコープオブジェクトを持つようにしただけ。
あとsetqは現在のスコープに書くのではなくdefineされたところまでたどってから書くらしいのでそう実装。
フィボナッチのために比較関数とか実装して終了。

        • -

まだSchemeのマクロとか継続とかは実装してないけど、そもそもマクロや継続を使ったSchemeのプログラムを書いたことがないのでどうしたものやら。
マクロのないSchemeを「Scheme作った」って言って公開したら叩かれないかな…とか言ってたらamachangに「1000人スピーカプロジェクト主催している人間が叩かれるのをおそれて公開しないなんてオマエハナニヲイッテイルンダ」と煽られたので公開しました。ぶってぶって。

        • -

id:higeponさんが激しくつっこんでくれるんじゃないかとほのかに期待。

つっこみまとめ
「consリストにしていないと後で泣く」「古典的マクロの実装は簡単」「えー、末尾呼び出しの最適化はしないのー(藁)」
amachangが自分のコードでは古典的マクロが簡単に実装できると言い出して、それをやられると僕もやりたくなるということで「業務時間内にはやらない協定」を結んだw
個人的にはリストをconsリストにするところと、ドットリストのサポートをしたい。