Lispはマクロと関数を区別する。同じ適用式でも、マクロの場合、引数を評価せずにASTのまま渡す。マクロ本体において、そのAST自体をLisp内の関数を用いてあれこれ処理し、ASTを返す。引数のASTの構造に手を入れられるため、文法そのものを拡張できる。マクロは式を返す。そしてその式自体がマクロ適用式の場合、評価されると更に別の式を返す。最終的にそれが関数適用から返された値となるまで、繰り返し評価を続ける。

Glispは、真にLisp的なマクロを提供しない。代わりに、その関数適用が1ステップ評価される際、どのようなASTが返されるべきかというアノテーションを関数本体に付与する機能を提供する。

例えば、円のPathオブジェクトを返す関数があるとする。

circle = (=> [center:Vec2 radius:Number]
	           '(path (M (Vec2 ~center.x ~(- center.y r)))
                    (C (Vec2 ...) ...)
                    ...
                    (Z)))

これは、関数本体がquoteされているので、Path値そのものではなく、path関数の適用式 (path (M (Vec2... のASTを返す。そしてそのASTが評価されることで、最終的にPath値が返される。

通常この関数が適用される場合、quote, unquoteといったアノテーションは無視され、ただ評価される。

しかし、この適用式がexpandされる場合、評価器はアノテーションに従って値ではなくASTを返す。

引数となる式は常にディープコピーされる。

Map関数のこと

map関数も本来こういう風にexpandされて欲しい。

(map inc [1 2 (+ 3 4)]) -> [(inc 1) (inc 2) (inc (+ 3 4))]