next up previous
Next: 発展問題 Up: ソフトウェア特論 講義資料 Scheme コンパイラ処理系 Previous: 10.6 クロージャの確認

11 リードマクロの利用

実際のscheme処理系では,tは,#t, nilは,#f という表記が使われま す.これらの表記を入力するとそれぞれt, nilとして扱われるようにするため に,Common Lispのリードマクロを再定義する機能により実装する方法が考え られます. まず, Schemeの組み込み関数readが 通常のLispの通常のread関数を呼び出すのではなく, scheme-readというこれから定義する関数を 呼び出すように,初期化用テーブルを次のように変更します.

(defparameter *scheme-procs*
  '(+ - * /
      abs sqrt sin cos atan
      = < > <= >=
      cons car cdr not append list
      member
      (read scheme-read) random name!
      (null? null) (eq? eq)
      (equal? equal) (eqv? eql)
      (compile scheme-compile)
      (exit scheme-exit)
      (number? numberp)
      (even? evenp) (odd? oddp)
      (write prin1) (display princ)
      (newline terpri)))
通常の状態で使っているリードマクロは,copy-readtable でコピーすることができます. リードテーブルは,利用可能な全文字ごとに 読み込み方を定義している関数を定義する関数を 登録してあるものです. この表の中で,#で始まり,その次に続く文字に 対応する関数を置き換える手続きとして, set-dispatch-macro-characterという関数が 用意されています. 新しく置き換えを行ったリードテーブルを 利用して通常のread手続きを行うには, 大域変数の*readtable*をその新しいリードテーブルに 局所的に置き換えて実行するということで 可能となります.その局所的置き換えには, letを使うことができます.letから抜ければ 通常のリードテーブルを利用することになります.

(defvar *scheme-readtable* (copy-readtable))

(defun scheme-read 
  (&optional (stream *standard-input*))
  (let ((*readtable* *scheme-readtable*))
    (read stream)))

(set-dispatch-macro-character #\# #\t 
  #'(lambda (&rest ignore) t)
  *scheme-readtable*)

(set-dispatch-macro-character #\# #\f 
  #'(lambda (&rest ignore) nil)
  *scheme-readtable*)


generated through LaTeX2HTML. M.Inaba 平成18年5月6日