Common Lisp でローカルな定数を導入する構文を作ろうとする記事を読んだ。
私は以前に似たようなことをやっていたことを思い出した。
》定数定義
以前に作ったマクロ define-constant は最終的に define に展開されるので、そのまま internal define に使っても機能はするのだが、あらためて let 系の形式でローカル定数を定義するマクロを書いてみることにした。
#!r6rs
(import (rnrs))
(define-syntax let-constant
(lambda(stx)
(syntax-case stx ()
((k ((var form) ...) body body* ...)
(with-syntax
(((t ...) (generate-temporaries #'(var ...))))
#'(let ((t form) ...)
(let-syntax
((var
(make-variable-transformer
(lambda(stx2)
(syntax-case stx2 ()
((set! v _)
(syntax-violation 'set!
"attempt to assign constant"
stx2
#'v))
(_ #'t))))) ...)
body body* ...)))))))
(let-constant ((x 1))
;;(set! x 2) ;; ← もし set! を試みたらエラーになる
(display x)))
例として書いた定数 x は識別子マクロで、展開後には隠れた変数に置き換えられる。 識別子マクロは set! で代入されるときの展開形を特別に定義することも出来て、ここではそういう形になっているときは syntax-violation を使って構文エラーになるように定義した。
Document ID: d5f61355b4e55961f2af8517178d2c53
0 件のコメント:
コメントを投稿