CLOSを利用した場合に、defmethodで定義したメソッドが組み込み関数と被るときの対処法
CommonLispの勉強のため、CLOS(Common Lisp Object System)を利用してスタック構造を実装しているところです。
スタック構造なので、メソッド名にpop
とpush
というのを定義したいのですが、CLOSの仕様上、そのまま定義しようとすると、既にCommon Lispの組み込み関数として定義されているpop
とpush
と被ってしまいます。このとき、メソッド名をリネームして衝突を回避することは可能だと思いますが、それよりはpop
・push
のメソッド名のまま利用したいと考えています。このとき、Common Lispではどのように解決するのが望ましいと言えるのでしょうか?
汚いですが、具体的なコードも掲載しておきます:
(defclass stack () ((state :accessor state :initform '())))
(defmethod push ((stack-obj stack) elem)
(let ((new-stack
(if (state stack-obj) (cons elem (state stack-obj)) (list elem))))
(setf (state stack-obj) new-stack)))
(defmethod pop ((stack-obj stack))
(let ((pop-stack (car (state stack-obj))))
(progn (setf (state stack-obj) (cdr (state stack-obj)))
pop-stack)))
また、sbcl
処理系を利用した場合のエラーメッセージは以下のようになります:
Unhandled SYMBOL-PACKAGE-LOCKED-ERROR in thread #<SB-THREAD:THREAD
"main thread" RUNNING
{10039B6833}>:
Lock on package COMMON-LISP violated when proclaiming PUSH as a function
while in package COMMON-LISP-USER.
See also:
The SBCL Manual, Node "Package Locks"
The ANSI Standard, Section 11.1.2.1.2