logoalt Hacker News

tsimionescu01/22/20251 replyview on HN

Visitor objects are needed when you want, at runtime, to decide what code to execute based on the types of two parameters of a function (regular OOP virtual dispatch can only do this based on the type of one argument, the one before the dot). While you can model this in different ways, there is nothing in "plain" Lisp (say, R7RS Scheme) that makes this particularly simple.

Common Lisp does have a nicer solution to this, in the form of CLOS generic functions. In CLOS, methods are defined based on the classes of all arguments, not just the first one like in traditional object systems. Combined with inheritance, you can implement the whole thing with the minimal amount of code. But it's still an OOP system designed specifically for this.


Replies

kazinator01/22/2025

The Visitor Pattern is one of the ones that actually does not go away when you have CLOS. That is to say the traversal and visitation part of it doesn't go away, just all the boiler plate around simulating the double dispatch, like needing two methods: accept and visit and whatnot.

Like say we want to visit the elements of a list, which are objects, and involve them with a visiting object:

  (mapcar (lambda (elem)
            (generic-fun visitor elem))
          obj-list)
We write all the method specializations of generic-fun for all combinations of visitor and element type we need and that's it.

Importantly, the traversal function doesn't have to know anything about the visitor stuff. Here we have mapcar, which dates back to before object orientation.

show 1 reply