#:g1: KMRCLを眺める (31) defconstant*

Posted 2009-12-05 10:56:00 GMT

今回は、KMRCLのmacros.lispの中からDEFCONSTANT*です。
DEFCONSTANT*は割と定番のマクロな気がします。
定義は、

(defmacro defconstant* (sym value &optional doc)
  "Ensure VALUE is evaluated only once."
   `(defconstant ,sym (if (boundp ',sym)
                          (symbol-value ',sym)
                          ,value)
     ,@(when doc (list doc))))
という感じで、変数を再度DEFCONSTANTしてしまうのを防ぐマクロです。
DEFCONSTANTは、コンパイル時やロード時に評価されるかどうかは処理系が好きにして良いらしく、SBCL等ではコンパイル時にも評価されます。
;; /tmp/foo.lispというファイル
(DEFCONSTANT +CONST+ 42)
;; SBCL
(COMPILE-FILE "/tmp/foo.lisp")
+CONST+
;⇒ 42
;; Allegro CL
(COMPILE-FILE "/tmp/foo.lisp")
+CONST+
;>>> Attempt to take the value of the unbound variable `+CONST+'.
というわけなので、SBCLだとファイルをロードしなくてもDEFCONSTANTの再定義でぶつかることがあります。
The constant +CONST+ is being redefined (from 42 to 43)
   [Condition of type DEFCONSTANT-UNEQL]
See also:
  Common Lisp Hyperspec, DEFCONSTANT [:macro]
  SBCL Manual, Idiosyncrasies [:node]
というようなエラーはSBCLだとライブラリを読み込むときに良く遭遇しますが、こういうケースをDEFCONSTANT*だと回避できるわけですね。

comments powered by Disqus