Scheme:マクロの移植性
マクロの移植性
schemeには、
- common-lisp系のdefine-macro,defmacro
- R5RS系列のdefine-syntax,syntax-rules,let-syntax,letrec-syntax
がありますが、
これらを一つのソースファイルで同時に使用できるのは、
- gosh
- guile
- scm
- bigloo?
ぐらいしかありません。
じゃあ、片方しか使うなというはなしもありますが、
- 展開に計算形を挟み込みたい
- マクロ引数の型で展開形式を変更したい
- 新しいシンボルをストリングと繋げて作りたい
は、R5RS-syntax-rulesでは記述できないように思います。 #展開形式にevalを含めることなしに
例(もっといい例があると思いますが)
(convter-code string symbol (-> (string-append (<- 'con) "cat" (<- 'inate)))) ;string と symbolというシンボルから string->symbol という繋がったシンボルを生成する必要がある ;もちろんstring,symbolに限らない(例えばユーザー型)のでR5RSのkeywordでやる方法は不可能
(また、私はsyntax-caseのsyntax-object->datum,datum->syntax-objectが胡散臭くて使う気になれません。 というか、define-macro型の方が自然にかけます。)
以前、WebPageをいろいろさぐってみると、
- define-macroをsyntax-caseで実現したというもの
- mzschemeの(require (lib defmacro));だったかな?
がありましたが、これらは、
- ユーザー定義のfree-variableが参照できない
という問題があったような気がします。
このような問題は、特に
- pltscheme,mzschemeなどのdefmacroがビルドインでない処理系
などを使用すると問題になりますが、 みなさん移植性を気にするとき、どのようになされていますか?
Shiro: ほんとうに移植性が重要なら、SLIB的に、defmacroみたいなものを 処理系毎に定義させて、それを使うという具合に1レイヤーかませるしか なさそうに思えます。legacy macroなら、たとえターゲットがサポートして いなくてもプリプロセスで何とか対応できるんじゃないでしょうか。
わりと「syntax-caseでいいじゃん」という意見も見ますね。 hygieneにどのくらいの重きを置くかってところで意見が別れそうです。
- fuyuki: hygienicにされたマクロをいやがる心理って てっぽーを手放したがらないアメリカの一部勢力に 通じるものがありやしないかなー というのをさっき思いついた。
せめてシンボルの生成くらいはr5rs内で出来て欲しいってのはありますね。
なお、「R5RS-syntax-rulesでは記述できない」というのはちょっとトリッキーな 言及で、Oleg KiselyovやAl Petrofskyあたりにそんなことを言うと 彼らはそんなマクロを書いて来てしまうような気がします。 (要はsyntax-rulesはそれだけでturing completeだって話なんですが)。