クロージャを教えるのは苦労じゃ
火曜日, 2月 12th, 2008大学に入ってすぐの頃、「クロージャって何ですか」と聞いたときの返答がこれでした。
そのときはCのstaticな変数と同じようなものかと理解したけど、
今思うと遠いような近いような……
大学に入ってすぐの頃、「クロージャって何ですか」と聞いたときの返答がこれでした。
そのときはCのstaticな変数と同じようなものかと理解したけど、
今思うと遠いような近いような……
R6RSではR4RSで登場したsyntax-caseが復活すると聞いていました。
確かに、R6RSの9.2節に
「syntax-caseでもdatum->syntaxを使わなければ衛生的なマクロが定義できる(12.6節参照)」
という説明がありましたが、syntax-caseという言葉が登場するのは恐らくそこだけで、
おまけに、R6RSは11章までしかありませんでした。
でも、よく見てみたら参照と書いてあるのは、標準ライブラリ(*)の12.6節でした。
R6RSの本体が90ページ(付録を除いても60ページ)もあるのに、
標準ライブラリの説明も70ページもあります。
英語がろくに読めない私にはあまりにも過酷です。
仕様書が薄いのがSchemeの特徴だったはずじゃ……
(*) Revised6 Report on the Algorithmic Language Scheme — Standard Libraries
—-
でも、syntax-caseが仕様に戻ったというのは嬉しいです。
syntax-ruleだけじゃ、私には使いこなせない気がするからです。
というのも、去年の夏休み、Common Lispでyaccもどきを作ったんです。
ただ、yaccのようにファイルに記述したBNFを読み取ってソースを吐き出すのではなく、
S式として記述してあるBNFを入力とし、Lispのプログラムを吐き出すマクロとして作りました。
例えば、次のような文法の構文解析器を生成したいとします。
E→E+T E→T T→T*F T→F F→<E> F→i
この場合は、次のように書きます。
(ここでは、構文解析と同時に計算もするものを作ってます)
(setf (symbol-function 'parser) (make-parser (E (E '+ T) (+ $1 $3) (T) $1) (T (T '* F) (* $1 $3) (F) $1) (F ('< E '>) $2 ('i) $1)))
そしたら、こんな関数が作られます。
#<CLOSURE :LAMBDA (#:G267) (LET ((#:G266 '(#:G253)) (#:G268 (POP #:G267))) (LABELS ((#:G265 (#:G269) (IF (EQ #:G268 '#:G252) (CAR #:G267) (CASE #:G269 ((#:G264) (CASE #:G268 ((#:G230) (LET (($1 NIL)) (SETF $1 (PROGN (POP #:G266) (POP #:G266) (POP #:G266))) (LET ((#:G292 (CAR #:G266))) (PUSH #:G268 #:G267) (SETF #:G268 'T) (PUSH $1 #:G267) (#:G265 #:G292)))) ((*) (LET (($1 NIL)) (SETF $1 (PROGN (POP #:G266) (POP #:G266) (POP #:G266))) (LET ((#:G291 (CAR #:G266))) (PUSH #:G268 #:G267) (SETF #:G268 'T) (PUSH $1 #:G267) (#:G265 #:G291)))) (以下略)
まあ、正直いいものとは言いがたいのですが、
とりあえず、動くものを作ることができました。
けど、実はCommon Lispのマクロをまともに使ったのはこれが初めてでした。
それでも問題なく書けたのは、マクロを使ったといっても、それは最初に入力を受け取る箇所だけで、
後は普通にLispの関数を書きなぐっただけだったからです。
だから、ボトムアップに開発を進めることができて、
関数単位でテストができたので、Cなんかで同じものを作るよりも、
圧倒的にデバッグが楽だったと思います。
しかし、これをR5RS通りのsyntax-caseがないSchemeで作ろうとすると、
syntax-ruleでマクロを書く必要があり、
syntax-ruleでは展開コードはテンプレートで記述する必要があり、
テンプレートからは普通のSchemeの関数を呼び出したりはできないので……
と、考えただけでも恐ろしいことになりそうです。
という訳で、Schemeを使ってマクロ展開コードを生成できるsyntax-caseが
復活したことに私は賛成です。(といっても、syntax-caseをいまいち分かってないんですが(笑))
R6RSを印刷すると紙の枚数が多くなる。
非常に重い。
持ち運びに不便。
ポータブルじゃない。
以前の日記で、R6RSに誤字がある?
と書いたのですが、R6RSの中の人に
「これって誤字ですか?」
とメールを送ってみたところ
「その通りだ」
って返事が返ってきました。
少しSchemeコミュニティに貢献した気分になれました。
R6RSの4.1. Notationに次のような記述があるんですが、
Some non-terminal names refer to the Unicode scalar values of the same name: <character tabulation> (U+0009), <linefeed> (U+000A), <carriage return> (U+000D), <line tabulation> (U+000B), <form feed> (U+000C), <carriage return> (U+000D), <space> (U+0020), <next line> (U+0085), <line separator> (U+2028), and <paragraph separator> (U+2029).
carriage returnが2回でてきます。
誤字かと思いErrataを見てみたんですが、まだないようです。
これって単なる誤字なんですかね。
実に3ヶ月ぶりでしょうか。
お久しぶりです。zickです。
本日、およそ半年ぶりにリリカルLispのソースをいじくりました。
大したことはしてないのですが、かなり戸惑いました。
NScripterの文法もかなり忘れ、悲しい限りです。
日記を書いてない三ヶ月間にも色々ありまして、
カップヌードルをずっと食べていなかったり、
かといって、それほどいい食生活を送っているわけでもなく、
試験前に欲しいゲームが発売して見事に単位を落としたり、
Erlangの勉強をしようと本を買って勉強していたり、
けれども、英語を読むのが遅くて時間が掛かったり……
まあ、あんまり面白くないのでこれくらいにしておきます(笑)
話は変わりますが、ほとんど更新してないのに足を運んでくれる皆様のために、
そろそろ何か少し大きいことでもやろうかと思います。
やはり、京都といえばλですね。
こんばんは。zickです。
さて、リリカルLisp通販も、あと数日で終了ですが、
結局大量に在庫が残っており、いまだに私の下宿の一部を占有しています。
大量に余った本とCDですが、捨てるのはさすがにもったいないですね。
というより、あれだけ苦労して作ったものを私には捨てることは出来ません。
捨てるぐらいなら、どこかで放流させたいですね(笑)
毎度のことながら、zickです。
通販の方ですが、結構反応がいいみたいです。
同人とかとは縁がなくても興味がある方は結構いたみたいです。
やっぱし通販やってよかったと思いました。
さて、Lisperの間で話題となったgauche.night。
私は残念ながら行けなかったのですが、小黒様のプレゼンの中で、
リリカルLispのスクリーンショットを使っていただきました。
とはいえ、どんな風に使っていただいたのかさっぱり分かってません。
そのときの写真とか撮られた方がいらっしゃいましたら、こっそり見せてください(笑)