クロージャを教えるのは苦労じゃ
火曜日, 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をいまいち分かってないんですが(笑))
「真のゆとり教育」が生んだ18歳天才プログラマー
ゆとり教育で「情報」の授業が必修になりましたが、
私の高校ではレポート一枚で終わりました。
翌年、その事実が発覚して色々大変なことになりました。
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ですが、捨てるのはさすがにもったいないですね。
というより、あれだけ苦労して作ったものを私には捨てることは出来ません。
捨てるぐらいなら、どこかで放流させたいですね(笑)