:name "rear-right-wheel") ,(make-instance 'body :name "body") ,(make-instance 'engine :name "engine"))))) ;; traverse to print elements ;; stream *standard-output* plays the role of other-object here (traverse #'print a *standard-output*) (terpri) ;; print newline ;; traverse with arbitrary context from other object (traverse #'do-something a 42) ;; traverse with arbitrary context from other object (traverse #'do-something a 'abc)) Output "front-left-wheel" "front-right-wheel" "rear-left-wheel" "rear-right-wheel" "body" "engine" kicking wheel "front-left-wheel" 42 times kicking wheel "front-right-wheel" 42 times kicking wheel "rear-left-wheel" 42 times kicking wheel "rear-right-wheel" 42 times don't know how "body" and 42 should interact starting engine "engine" 42 times kicking wheel "front-left-wheel" symbolically using symbol ABC kicking wheel "front-right-wheel" symbolically using symbol ABC kicking wheel "rear-left-wheel" symbolically using symbol ABC kicking wheel "rear-right-wheel" symbolically using symbol ABC don't know how "body" and ABC should interact starting engine "engine" symbolically using symbol ABC Notes The other-object parameter is superfluous in traverse. The reason is that it is possible to use an anonymous function that calls the desired target method with a lexically captured object: (defmethod traverse (function (a auto)) ;; other-object removed (with-slots (elements) a (dolist (e elements) (funcall function e)))) ;; from here too ;; ... ;; alternative way to print-traverse (traverse (lambda (o) (print o *standard-output*)) a) ;; alternative way to do-something with ;; elements of a and integer 42 (traverse (lambda (o) (do-something o 42)) a) Now, the multiple dispatch occurs in the call issued from the body of the anonymous function, and so traverse is just a mapping function that distributes a function application over the elements of an object. Thus all traces of the Visitor Pattern disappear, except for the mapping function, in which there is no evidence of two objects being involved. All knowledge of there being two objects and a dispatch on their types is in the lambda function. Python example Python does not support method overloading in the classical sense (polymorphic behavior according to type of passed parameters), so the "visit" methods for the different model types need to have different names. Sources """ Visitor pattern example. """ from abc import ABCMeta, abstractmethod NOT_IMPLEMENTED = "You should implement this." class CarElement: __metaclass__ = ABCMeta @abstractmethod def accept(self, visitor): raise NotImplementedError(NOT_IMPLEMENTED) class Body(CarElement): def accept(self, visitor): visitor.visitBody(self) class Engine(CarElement): def accept(self, visitor): visitor.visitEngine(self) class Wheel(CarElement): def __init__(self, name): self.name = name def accept(self, visitor): visitor.visitWheel(self) class Car(CarElement): def __init__(self): self.elements = [ Wheel("front left"), Wheel("front right"), Wheel("back