2009年9月1日火曜日

include マクロ

includeというマクロを書いてみた。 別ファイルに書かれてあるS式を、ソースの中に埋め込むマクロだ。 loadと似ているが、呼び出した場所の環境で評価される点が違う。

include.scm

;; ファイルに書かれているS式を埋め込むマクロ。
;; 使い方:  (include ファイル名)
;; ただし、ファイル名には文字列かトップレベルの変数しか指定できない
(defmacro include (fname)
  (let ((read-all
         (lambda (port)
           (let lp ((e (read port)) (result (list)))
             (if (eof-object? e) (reverse! result)
                 (lp (read port) (cons e result)))))))
    `(begin ,@(call-with-input-file 
                (eval fname (interaction-environment))
                (lambda (p) (read-all p))))))

適当なサンプルで動作確認

$ cat tmp2.scm    # 埋め込むファイル
  (display 
     (format "a=~A b=~A (foo a b) = ~A\n" a b (foo a b)))
  (foo a b)

$ gosh
  gosh> (load "./include.scm")
  gosh> (define file "tmp2.scm")
  gosh> (define foo +) (define a 10) (define b 20) ;; toplevel設定
  gosh> (let ((foo *) (a 11)) (load file))    ;; loadの実行結果
     =>  a=10 b=20 (foo a b) = 30
         #t
  gosh> (let ((foo *) (a 11)) (include file)) ;; includeの実行結果
     => a=11 b=20 (foo a b) = 220
        220
  gosh> ^D

変数 foo,a,bについて、 loadの場合はトップレベルの定義で評価されているが、 includeでは、(let ...) バインドの値で評価されているのが確認できる。

0 件のコメント:

コメントを投稿