Shammer's Philosophy

My private adversaria

LISP で Queue を実装その2

LISP で Queue を実装その1 - Shammerismの失敗を回避するためにクラスを使用。

? (defclass queue ()
((internal-list :reader get-internal-list :writer set-internal-list)))
#<STANDARD-CLASS QUEUE>
? (defmethod en-queue ((q queue) object)
(let ((original-queue (if (slot-boundp q 'internal-list)
                          (get-internal-list q)
                          nil)))
  (let ((new-queue (append original-queue (list object))))
    (set-internal-list new-queue q))))
#<STANDARD-METHOD EN-QUEUE (QUEUE T)>
? (defparameter test-queue (make-instance 'queue))
TEST-QUEUE
? (en-queue test-queue 'a)
(A)
? (en-queue test-queue 'b)
(A B)
? (get-internal-list test-queue)
(A B)
?

en-queue の中で null check をしなかった場合、「Slot INTERNAL-LIST is unbound」のエラーになるので null check をしている。まあ、これは初期値を nil で定義しておいてもいいかも。そのように書き換えた方がいいか。そうすれば en-queue はよりシンプルにできる。中身を取り出す de-queue は以下のようになった。空のときには nil を返すように気を付ける必要がある。

? (defmethod de-queue ((q queue))
(let ((return-object nil))
  (when (slot-boundp q 'internal-list)
    (let ((original-list (get-internal-list q)))
      (setf return-object (car original-list))
      (set-internal-list (cdr original-list) q)))
  return-object))
#<STANDARD-METHOD DE-QUEUE (QUEUE)>
?

en-queue と de-queue を繰り返して実行してみた。とりあえず、LISP で Queue を実装その1 - Shammerismで想定していたことはできていると思ってよさそうだ。

? (defparameter test-queue (make-instance 'queue))
TEST-QUEUE
? (de-queue test-queue)
NIL
? (en-queue test-queue 0)
(0)
? (en-queue test-queue 1)
(0 1)
? (en-queue test-queue 2)
(0 1 2)
? (de-queue test-queue)
0
? (en-queue test-queue 0)
(1 2 0)
?