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 has 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 now displays five slots, numbered from 0
to 4
with values "mary"
"had"
"a"
"little"
and "lamb"
.
The following example modifies the above call to get-inspector-values
so that it inspects cells rather than their value slots. The setter updates the next-cell
. Use this new mode to inspect the "lamb"
cell and then set its next-cell
slot to (make-dll "with" "mint" "sauce").
The expanded sentence can now be inspected in the follow-links
mode.
(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")))