Okay, now that we have established that the Visitor pattern is actually about mapping, as Tim said, we can give an example:
Given nodes of a tree, with data and children.
(defstruct node d c)
We can define a map function:
(defun mapt (n f s k) (when n (funcall f (funcall k n)) (mapc (lambda (n) (mapt n f s k)) (funcall s n))))
The mapt function takes a start node, a function to apply on each node's data, the successor function and a key function that extracts the data from the node.
With generic functions we can provide content specific behavior. Here eventually PRINT-OBJECT will do the right thing.
Usually Lisp provides these mapping functions. For example in LispWorks CAPI:MAP-PANE-CHILDREN walks over the sub panes of a pane.
That's what he was talking about, there is no special Visitor pattern implementation, just mapping over the object structure. The mapping function depends on what it is, a tree, a cyclic graph, ...
So, writing functions to visit your data structures is not "the Visitor pattern"? That's exactly the point of my original post; Lisp thinks they invented everything and do everything in their own amazing way, when in reality, they solve the same problems the same way as everyone else.
Given nodes of a tree, with data and children.
(defstruct node d c)
We can define a map function:
(defun mapt (n f s k) (when n (funcall f (funcall k n)) (mapc (lambda (n) (mapt n f s k)) (funcall s n))))
The mapt function takes a start node, a function to apply on each node's data, the successor function and a key function that extracts the data from the node.
Then we can call it, printing all node contents:
(mapt #S(NODE :D 1 :C (#S(NODE :D 2 :C NIL) #S(NODE :D 3 :C NIL))) #'print #'node-c #'node-d))
With generic functions we can provide content specific behavior. Here eventually PRINT-OBJECT will do the right thing.
Usually Lisp provides these mapping functions. For example in LispWorks CAPI:MAP-PANE-CHILDREN walks over the sub panes of a pane.
That's what he was talking about, there is no special Visitor pattern implementation, just mapping over the object structure. The mapping function depends on what it is, a tree, a cyclic graph, ...
I found Tim's post not really that painful...