Let's start Scheme

2012-10-02

絶対に明文化されないライブラリのメモ

Sagittariusには開発者が既存の機能のバグをビルドすることなくテストするライブラリがあったりする。(実際はライブラリという形式を取っているだけで、そういう機能があるのだが)。
この機能は僕が(主にマクロ展開器の)バグ取りように使うだけという位置づけにしてあるものの、普通にライブラリとして提供されている。ドキュメント化は絶対されないし、するつもりもない。っが、遊びとして使う分には面白い機能なので、興味がある人は触ってもいいかなぁと思いメモ。(と将来の自分への備忘録)

ライブラリは(現状では)(sagittarius aspect)という名前で提供されていて、このライブラリは(Again現状では)point-cutというマクロを提供している。名前付けは正直微妙だなぁと思っているので、将来のバージョンでは変更になるかもしれない。まぁ、でも使用頻度はそうないしこのままかもしれない。
使い方は以下のようになる。
(import (sagittarius aspect))
(point-cut
  (core syntax-case)
  expand-syntax
  (lambda (vars template ranks id-lexname lexname-check-list p1env)
     (let ((r (proceed)))
        (print r)
        r)))
マクロがproceedという手続きを提供するので、単に結果を覗きたいだけならこんな感じで書ける。結果が意にそぐわないものであれば変更も出来る。また、オリジナルの処理をせずに(proceedを呼ばずに)自分で再実装しても構わない。
気をつける点は、そのライブラリで定義された手続き自体を変更するということ。この変更がどこかのライブラリの挙動を変更するのである。例としては、
(library (foo)
    (export bar)
    (import (rnrs))
  (define (bar) 'bar))

(library (hoge)
    (export fuga)
    (import (rnrs) (foo))
  (define (fuga) (display (bar)) (newline) 'fuga))

(import (hoge))
(fuga)     ; prints bar and returns fuga

(import (sagittarius aspect))
(point-cut (foo) bar (lambda () 'gehehe))
(fuga)     ; prints gehehe and returns fuga
上記の例では、手続きfugaは一切変更されていないが、依存するライブラリ(foo)内で定義された手続きbarが変更されているので、fugaに影響が起きている。モジュールシステムそのものを破壊する禁じ手ではあるのだが、使い方によっては便利に使えるので入れてある(自分用)。

そういえば、似たような機能で明文化されているのはwith-libraryマクロだろう。あっちはオリジナルを実行して値を覗くということは出来ないが。

No comments:

Post a Comment