common-lispclos

Optional Arguments in defgeneric?


I'm writing some methods to emit HTML for various elements. Each method has the same output, but doesn't necessarily need the same input.

The method for echoing a game-board needs to take a player as well (because each player only sees their own pieces)

(defmethod echo ((board game-board) (p player)) ... )

Echoing a board space doesn't require changing per player (that dispatch is actually done in the game-board method, which later calls echo on a space). Ideally, I'd be able to do

(defmethod echo ((space board-space)) ... )
(defmethod echo ((space empty-space)) ... )

It's also conceivable that I later run into an object that will need to know more than just the player in order to display itself properly. Since there are already methods specializing on the same generic, though, that would give the error

The generic function #<STANDARD-GENERIC-FUNCTION ECHO (4)> takes 2 required arguments;

It seems less than ideal to go back and name these methods echo-space, echo-board and so on.

Is there a canonical way of varying other arguments based on the specialized object? Should I do something like

(defgeneric echo (thing &key player ...) ...)

or

(defgeneric echo (thing &rest other-args) ...)

? More generally, can anyone point me to a decent tutorial on defgeneric specifically? (I've read the relevant PCL chapters and some CLOS tutorials, but they don't cover the situation I'm asking about here).


Solution

  • Generally speaking if interfaces of two functions are too different it indicates that they are not actually a specializations of the same operation and should not have the same name. If you only want to specialize on optional/key arguments the way to achieve that is to use a normal function which calls a generic function and provides it with default values for missing arguments to specialize on.

    Keene's book is, I believe, the most comprehensive guide to CLOS. Unfortunately it seems to be available only in book form.