#:g1: リーダーマクロで略語/リテラル表現 その一

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

今回は、リーダーマクロで略語/リテラル表現 その一です。

略語

『'』

略語として最も身近で代表的なものといえば、『'』です。'Xは、(quote X)と展開され、(quote X)がevalによって評価されると、Xそのものを返すところから、quote(引用)ということになります。リーダーマクロのパターンとしても最も基本のもので、次の一つの式をREADで読んで、式の引数とする、というタイプになります。

リテラル表記

Lispでのリテラル表記は、大抵リード時にオブジェクトが作成されます。'(1 2 3)や、'#(1 2 3)は、リード時に(list 1 2 3)や、(vector 1 2 3)を実行し、それらのオブジェクトをクォートしたものと同じで、定数として扱われます。リストとシンボルは、実行フォームとしても評価されるので、フォームではない場合はクォートする必要がありますが、リストとシンボル以外は、クォートしてもしなくても良いことが殆どです。

式/リスト 『(』

Lispでは空気のような()ですが、これもリーダーマクロです。リード時に『(』から『)』の間を要素とするリストを作成しますが、ドットの扱い等があるので、細かくみていくと実は結構複雑です。()をカスタマイズするのは、影響が甚大なので難易度が高いですが、できなくもありません。アイデアが有効かどうか、というところですね。

配列

配列にも多次元配列や、一次元のベクタがありますが、記法もそれぞれです。

『[』

Emacs lispや、Clojureでは、ベクタをリストのように、[1 2 3]とブラケットで記述します。CLも当初この記法を採用しようという意見があったようですが別の方式になってしまいました。

『#(』

Common Lisp/Schemeだと、#(1 2 3)のように書きます。SRFI-4は、要素の型が同じベクタの規定ですが、#u8(1 2 3)のように書くことになっています。u8は、8bitのunsigned integerで、s16、f32等も指定できます。

『#A(』

多次元配列は、CLの場合、次元を指定して、#2A((1 2 3) (4 5 6))のように書くことが可能です。CLのディスパッチマクロ文字は、#と文字の間に十進数の引数を取ることができるのですが、#Aというマクロ文字が引数として2という次元を取る、という解釈になっています。
Schemeの場合は、SRFI-58で多次元配列の記法が定義されていますが、#2*3:fixN16b((0 1 2) (3 5 4))のように型を指定しつつ次元も指定したりで全部指定すると凄いことになります。これらも、リード時に引数を解釈し、(make-array '(2 3) :element-type 'fixN16b :init '((0 1 2)..))的なものに展開されて実行される、という流れです。

その他の例

CLだと、#*01010101というような『#*』による表記で、要素が0か1かに限定されたベクタ(bit-vector)を表記することが可能です。ディスパッチマクロ文字の場合、引数の扱いがどうなっているかを探るのが、なかなか面白いところでもありますが、#*の場合
#10*0
;=>  #*0000000000
となります。要素の長さを指定する、という訳ですね。

まとめ

略記とリテラル表記の基本的なところを解説してみました。あまり解説になってない気もしますが、リード時というものを意識するきっかけ位になれれば良いなと思います。
次回は、リーダーマクロで略語/リテラル表現 その二 です。

comments powered by Disqus