Stack in Common Lisp (Vector ver.)

スタックを Common Lisp で書いてみたものの、思い直して組み込み vector-push, vector-pop を使うことにした。
vector は一次元配列のこと。

(defclass vm () ;; stack machine
  ((codes :accessor codes :initform nil)
   (stack :accessor stack :initform (make-array *max-stack* :initial-element nil :fill-pointer 0))
   (pc :accessor pc :initform 0)
   (fp :accessor fp :initform 0)
   ))

(defmethod vm-push ((vm vm) n)
  (with-slots (stack) vm
    (vector-push n stack)))

(defmethod vm-pop ((vm vm))
  (with-slots (stack) vm
    (vector-pop stack)))

(defmethod vm-top ((vm vm))
  (with-slots (stack) vm
    (aref stack (1- (fill-pointer stack)))))

Common Lisp の fill-pointer というのが実質 stack pointer になる。
以下は要素3の配列 v を作って、スタックとして操作してみたもの。


vector-pop を使っても、aref によって直接参照すると値(ここでは'c)が残っている。
そういうものか、と思って HyperSpec を調べたらまさに定義どおりの動作なのだった。
(http://www.lisp.org/HyperSpec/Body/fun_vector-pop.html)
さらに, fill-pointer が指定されている vector は、そこまでしか印字されない、ともちゃんと規定されていた(http://www.lisp.org/HyperSpec/Body/sec_22-1-3-7.html)。

st-machine(15): (setq v (make-array 3 :initial-element 0 :fill-pointer 0))
#()
st-machine(16): (vector-push 'a v)
0
st-machine(17): (vector-push 'b v)
1
st-machine(18): (vector-push 'c v)
2
st-machine(19): v
#(a b c)
st-machine(20): (vector-push 'd v)
nil
st-machine(21): v
#(a b c)
st-machine(22): (fill-pointer v)
3
st-machine(23): (vector-pop v)
c
st-machine(24): (fill-pointer v)
2
st-machine(25): v
#(a b)
st-machine(26): (aref v 2)
c


よく参考にさせてもらっている http://www.geocities.jp/m_hiroi/xyzzy_lisp/abclisp05.html が詳しい。