#:g1: mbeの紹介

Posted 2014-02-18 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の50日目です。

mbeとはなにか

 mbeはDorai Sitaram氏によるEugene Kohlbecker氏のMacro by Example(R4RSの付録のマクロ)の実装です。

パッケージ情報

パッケージ名mbe
プロジェクトサイト Macro by Example

インストール方法

 Common Lispの場合は、サイトから拾ってきて適当にロードします。
ちなみに、私がASDFでロードできるようにしたものもありますので興味のある方はどうぞ

 Schemeの場合は、slibに含まれているので、slibをロードできる処理系では、slibでの導入が簡単かと思います。

Gaucheの場合

(use slib)
(require 'common-list-functions)
(require 'rev4-optional-procedures)
(require 'defmacroexpand)
(require 'macro-by-example)

試してみる

 Common Lisp版とScheme版がありますが、Common Lispをメインに紹介してみます。
とはいえ、プロジェクトのサイトに丁寧に解説されているので、利用にあたってざっと簡単なところを紹介

Common Lisp版は衛生マクロでない

 Common Lisp版は、100行程度のシンプルな実装ですが、変数の衝突を自動で回避してくれる仕組みは入っていません。
withという変数のリネーム用の構文があるので、これで手動gensymして回避します。

Scheme版
(define-syntax kandi
  (syntax-rules ()
    ((kandi arg ...)
     (let ((a 1) (b 2) (c 3))
       (list a b c arg ...)))))

(kandi 1 2 3) ;==> (let ((slib:G290 1) (slib:G291 2) (slib:G292 3)) (list slib:G290 slib:G291 slib:G292 1 2 3))

Common Lisp版
(define-syntax kandi
  (syntax-rules ()
    ((kandi arg ***)
     (with ((a (gensym))
            (b (gensym))
            (c (gensym)))
       (let ((a 1) (b 2) (c 3))
         (list a b c arg ***))))))

(kandi 1 2 3) ;==> (LET ((#:G3504 1) (#:G3505 2) (#:G3506 3)) (LIST #:G3504 #:G3505 #:G3506 1 2 3))

バグ?: Common Lisp版

 ちなみにCommon Lispのオリジナルの実装では、ネストしたパタンの展開でバグがあるようですので、修正githubに置いてあるものは修正してあります。
このパタンはScheme版ではちゃんと展開するようです。

(define-syntax badios
  (syntax-rules ()
    ((badios (a ***) (b ***))
     (list (b a) ***))))

(badios (1 1 1 1) (2 2 2 2)) ;==> (LIST (B 1) (B 1) (B 1) (B 1)) ;??? ;==> (LIST (2 1) (2 1) (2 1) (2 1))

Common Lisp/Scheme版共通
(define-syntax baz2
  (syntax-rules ()
    ((foo (a ... b) ...)
     (append (list a ... '(b)) ...))))

のようなパタンはエラーになるようです。
他にもつつけば色々ある気はしますが、実用上ではそんなに困ることもないかなと思います。

mbeの紹介/関連記事等

まとめ

 今回は、mbeを紹介してみました。
自分は、SRFIのCommon Lispへの移植でdefine-syntaxを利用しているものは、mbeを使って移植してみていましたが、大き目の込み入ったマクロでもほぼそのまま動かすことができました。
衛生的ではないもののSchemeからCommon Lispにコードを移植する際には、かなり便利ですのでお勧めです。

comments powered by Disqus