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)
をデフォルトで入れるようにしよう。これがあって困るケースは今の時点では思い浮かばない。