#:g1: リーダーマクロでコメント

Posted 2012-12-05 15:00:00 GMT

リーダーがいじれる系に関しては、五日目 @sirohuku さんが紹介されたRacketのリーダーの差し替えがほぼ最強ですので、これ以上のものはありません…。リーダーマクロネタをどういう風に展開していったら良いか悩みましたが、既存のLisp方言のリーダーマクロを集めて眺めてみたところ、それなりにパターンがあるようだったので、パターンごとに地味に解説してみることにしました。
今回は、コメントをどういう風にリーダーマクロで実現しているかの解説です。

リーダーマクロでコメント

『;』

Lisp系でコメント文字は、『;』というのが伝統的ですが、そもそも『;』はリーダーマクロなのか、という話もあるかと思います。一応Common Lispでは、HyperSpecの2.1.4 Character Syntax Typesにあるようにterminating macro charと定義されていて、挙動は、2.4 Standard Macro Characters>2.4.4 Semicolonで定義されています。ユーザーがリーダーマクロを定義できる場合は、こういう実現も自然といえば自然かもしれません。terminatingというのは、foo;と書いても、fooと;とに別々に読まれるということで、non-terminatingだと、foo ;と書かない場合は、foo;と読まれます。それで『;』の動作ですが、リーダーは『;』という文字に出会うと、そこから改行までを読み捨てます(改行より前にEOFに出会ったらそこまでを読み捨て)。自分も四日目の@ponkoreさんの記事で知ったのですが、Clojureは『#!』も『;』の動きをするとのこと、確かにUnix系のシェルからの実行を考えると便利かもしれないですね。
(+ 1 1) ; 1足す1
の場合、; 1足す1は読み捨てられます。

練習問題 1. 『;』のようなコメント機能をリーダーマクロとして作成してみましょう

実装のコードを貼っても良いのですが、面倒なので練習問題として提案してみることにしました。利用しているLisp処理系の実装を眺めつつ実際に作ってみると色々面白いかなと思います。

『#|』

C系では、//のコメントと/* */の範囲コメントがありますが、Lisp系だと範囲コメントは、#|コメント|#と書くことが多いかと思います。Common Lispの場合、この#|もリーダーマクロです。Schemeの場合は、SRFI 30: Nested Multi-line Commentsで定義されていて、R6RSから仕様の中でも規定されています。C系の/* */と違うのは、#||#はネストが可能ということ。#|の二文字で構成されていることから分かるように、#|はCommon Lispではディスパッチマクロ文字です。
(+ 1 #|コメント #|コメント中のコメント |#|# 1)
は、(+ 1 1)と読まれます。

練習問題 2. 『#|』のようなコメント機能をリーダーマクロとして作成してみましょう

『#;』

『;』や『#|』は古くから存在しますが、SRFI 62: S-expression commentsのように、後続の一つの式を読み飛す、というタイプがあります。Clojureだと『#_』で同じことをするようです。(@ponkoreさんによるClojureのリーダーマクロの解説)
(+ 1 1 #;1)
は、(+ 1 1)と読まれます。

練習問題 3. 『#;』のようなコメント機能をリーダーマクロとして作成してみましょう

その他の例

1980年代に存在した、LSB(Layered System Building)(PDF)という方言の上に共通言語を構築する試みでは、
{-- コメント...}
{-*- コメント...}
のように、{}の中で、--もしくは、-*-で開始された場合は、以降を読み捨てる、というものがあったようです。

練習問題 4. LSBの『{--}・{-*-}』のようなコメント機能をリーダーマクロとして作成してみましょう

まとめ

コメント開始の文字もLispでは、リーダーマクロを利用して実現されていることを解説してみました。ついでの練習問題として、

練習問題 5. C系の『//』のようなコメント機能をリーダーマクロとして作成してみましょう

練習問題 6. Cの『/* */』のようなコメント機能をリーダーマクロとして作成してみましょう

のようなものも考えられるかと思います。

具体的な実装についての解説はなしなのか、という感じですが、残りのAdvent Calendar上で、主にCommon Lispで解説したいと思いますので、作れる人は実装してみる、という感じで流しておいて下さい。

次回は、リーダーマクロによりリード時に処理系依存コードを切り分けるという手法を解説します。

comments powered by Disqus