Shammer's Philosophy

My private adversaria

defpackage の :use を使う

関数を生成するマクロ・その3 - Shammerismで言及したパッケージの問題。対処がわかったのでメモ。まず、default のパッケージは COMMON-LISP-USER になる。

? *package*
#<Package "COMMON-LISP-USER">
?

なので、パッケージを移動することなく作成された関数は、この COMMON-LISP-USER パッケージに存在している。一方で、オリジナルの、というかビルトインの関数(list とか apply とか)は、CCL というパッケージに存在していた(これは ClozureCL の場合)。なので、別パッケージに移動したときに default のパッケージで作成した関数を使用できないのは、別パッケージで COMMON-LISP-USER パッケージを使用できるようにしていないためで、CCL はパッケージが何であろうと使用できるようになっている、と言えないだろうか。

? (let ((public-symbols nil))
  (defun public-symbol (s)
    (push s public-symbols))
  (defun get-public-symbol ()
    public-symbols)
  (defun export-public-symbol ()
    (export public-symbols)
    (setf public-symbols nil)))
EXPORT-PUBLIC-SYMBOL
? (public-symbol 'public-symbol)
(PUBLIC-SYMBOL)
? (public-symbol 'get-public-symbol)
(GET-PUBLIC-SYMBOL PUBLIC-SYMBOL)
? (public-symbol 'export-public-symbol)
(EXPORT-PUBLIC-SYMBOL GET-PUBLIC-SYMBOL PUBLIC-SYMBOL)
? (export-public-symbol)
NIL
? *package*
#<Package "COMMON-LISP-USER">
? (defpackage "TEST")
#<Package "TEST">
? (in-package test)
#<Package "TEST">
? (defun say-hello () (format t "Hello~%"))
SAY-HELLO
? (common-lisp-user:public-symbol 'say-hello)
(SAY-HELLO)
? (common-lisp-user:export-public-symbol)
NIL
? (in-package common-lisp-user)
#<Package "COMMON-LISP-USER">
? (test:say-hello)
Hello
NIL
? (in-package test)
#<Package "TEST">
? (use-package 'common-lisp-user)
T
? (get-public-symbol)
NIL
? (in-package common-lisp-user)
#<Package "COMMON-LISP-USER">
? (defpackage "XXX" (:use common-lisp-user))
#<Package "XXX">
? (in-package xxx)
#<Package "XXX">
? (get-public-symbol)
COMMON-LISP:NIL
?

export は CCL パッケージだからどのパッケージからでも使用できるので、独自に export を呼び出す処理を COMMON-LISP-USER で作成して、それを別のパッケージから呼出してみた。予想通り、defpackage の :use で common-lisp-user を指定することで CCL と同じように呼び出すことができるようになる。今後はパッケージは

(:use common-lisp-user)

をデフォルトで入れるようにしよう。これがあって困るケースは今の時点では思い浮かばない。