2011/05/18

gauche に macrolet

私が書いたものではなく@kikuchan98さんが書いたものです。
ネタ元はもちろんcommon lispのmacrolet。どこまでcommon lispのmacroletと同様に動作するかはまだ不明です。

やろうと思えばこんなことまでできるんですね。

(define-macro (macrolet letargs . body)
  `(let-syntax
       ,(map (lambda (elm)
               (cons (car elm) `((,(with-module gauche.internal make-macro-transformer) (gensym) ,(cadr elm)))))
             letargs)
     ,@body))
(display
 (let ((n 9))
   (macrolet ((hoge (lambda x `(list ,@x)))
              (fuge (lambda x `(+ ,@x)))
              (square (lambda (x)
                        (let ((g!x (gensym)))
                          `(let ((,g!x ,x))
                             (* ,g!x ,g!x))))))
             (hoge 1 2 (fuge 1 2 3)(square (inc! n)))))
 )

;; -> (1 2 6 100)#<undef>


(undocumentedな?gauche.internalモジュールのmake-macro-transformerが使われています。というかユーザーが使うことは想定されていないものですよね・・・。なんつってもinternalですしおすし。)

@kikuchan98さんは自称LISP初心者ですが、gaucheでサクッとtemplate engineを書いたり、jsonに.(ドット)記法でアクセスできるwith-jsonマクロをgaucheでサクッと書いたり、すげーっす。。
曰く、伝統的マクロを書くということ(というよりLOLで言うところのquasiquoteの梯子の昇降か)はCのポインタ操作と似ていて馴染みやすいそうです。

ところでgaucheはあのソースコードが、あのプロジェクト全体が、一体どうやって管理されているのか私にはさっぱり想像できません。
これはgaucheソースコードリーディング勉強会(年単位で終わるのか・・・?)フラグかも。9LISPで。

追記

R6RSで書いてみた(define-syntax let-identifier-syntax(syntax-rules()((_((i f)...)b ...)(let-syntax((i(identifier-syntax f))...)b ...))))
(define-syntax let-identifier-syntax
  (syntax-rules ()
    ((_ ((i f) ...) b ...)
     (let-syntax ((i (identifier-syntax f)) ...)
       b ...))))
R6RSのマクロは複雑そうなので手がです・・・。伝統的マクロで良いかな、と。まだ今後のお楽しみ。

プログラミングGauche

0 件のコメント:

コメントを投稿