Consider the following implementation of doubly-linked lists.
(in-package "DLL")
(defstruct (dll (:constructor construct-dll)
(:print-function print-dll))
previous-cell
value
next-cell)
(defun make-dll (&rest list)
(loop with first-cell
for element in list
for previous = nil then cell
for cell = (construct-dll :previous-cell cell
:value element)
doing
(if previous
(setf (dll-next-cell previous) cell)
(setq first-cell cell))
finally
(return first-cell)))
(defun print-dll (dll stream depth)
(declare (ignore depth))
(format stream "#<dll-cell ~A>" (dll-value dll)))
You can inspect a single cell by inspecting the following object:
(dll::make-dll "mary" "had" "a" "little" "lamb")
The resulting Inspector shows three slots:
dll::previous-cell
with value
nil
,
value
with value
"mary"
and
dll::next-cell
with value
#<dll-cell had>
.
In practice, you are more likely to want to inspect the whole doubly-linked list in one window. To do this, define the following method on
get-inspector-values
.
(in-package "DLL")
(defun dll-root (object)
(loop for try = object then next
for next = (dll-previous-cell try)
while next
finally
(return try)))
(defun dll-cell (object number)
(loop for count to number
for cell = object then (dll-next-cell cell)
finally
(return cell)))
(defmethod lw:get-inspector-values ((object dll)
(mode (eql 'follow-links)))
(let ((root (dll-root object)))
(values
(loop for cell = root then (dll-next-cell cell)
for count from 0
while cell
collecting count)
(loop for cell = root then (dll-next-cell cell)
while cell
collecting (dll-value cell))
nil
#'(lambda (object key index new-value)
(declare (ignore key))
(setf (dll-value (dll-cell (dll-root object) index)) new-value))
"FOLLOW-LINKS")))
Inspecting the same object with the new method defined displays a new tab in the Inspector "Follow Links". This shows five slots, numbered from
0
to
4
with values
"mary"
"had"
"a"
"little"
and
"lamb"
.
The following example adds another method to
get-inspector-values
which inspects cells rather than their value slots. The cells are displayed in a "Fllow Cells" tab of Inspector. The setter updates the
next-cell
. Use this new mode to inspect the
"lamb"
cell - that is, double-clink on the
"lamb"
cell in the "Follow Cells" tab - and then set its
next-cell
slot to
(make-dll "with" "mint" "sauce")
.
(in-package "DLL")
(defmethod lw:get-inspector-values
((object dll) (mode (eql 'follow-cells)))
(let ((root (dll-root object)))
(values
(loop for cell = root then (dll-next-cell cell)
for count from 0
while cell
collecting count)
(loop for cell = root then (dll-next-cell cell)
while cell
collecting cell)
nil
#'(lambda (object key index new-value)
(declare (ignore key))
(setf (dll-next-cell (dll-cell (dll-root object) index)) new-value))
"FOLLOW-CELLS")))
The extended sentence can now be inspected in the
follow-links
mode.