I notice, upon reading Keene's book, that defgeneric
has a :method
option, which seems like it allows you to specify a method in the generic definition itself. Most documentation I've seen has all of the applicable methods defined in separate defmethod
s. The hyperspec, with its usual clarity, lists :method
as an option for defgeneric
, but does not say what it means.
Does the :method
option present a default, or at least, document what you expect the most common use case will be, or does it have additional semantics? As a style point, if you expect to define only one method, does it make more sense to define it in the defgeneric
form (if you can, indeed, do that), or separately in a defmethod
? Or does it not make sense to make a generic function in this case at all, and instead use a regular defun
?
The hyperspec, with its usual clarity, lists :method as an option for defgeneric, but does not say what it means.
Actually, the HyperSpec entry for defgeneric, with its usual clarity, says exactly what it means. It says the syntax for defgeneric is:
defgeneric function-name gf-lambda-list [[option | {method-description}*]]
and then says that the syntax for method-description is:
method-description::= (:method method-qualifier* specialized-lambda-list [[declaration* | documentation]] form*)
And then it describes method-combination:
Each method-description defines a method on the generic function. The lambda list of each method must be congruent with the lambda list specified by the gf-lambda-list option. If no method descriptions are specified and a generic function of the same name does not already exist, a generic function with no methods is created.
So the :method forms are for defining methods on the generic function, just like defmethod forms.
(I will grant that it doesn't really say anything about why you'd prefer defgeneric plus :method as opposed to defmethod. Remember that the Common in Common Lisp means that the language is an attempt to unify lots of existing Lisp implementations. Maybe some supported :method and others supported defmethod, and this was the easiest way to provide a unified interface.)
That is, the following would have the same effect:
(defgeneric to-list (object))
(defmethod to-list ((object t))
(list object))
(defmethod to-list ((object list))
object)
(defgeneric to-list (object)
(:method ((object t))
(list object))
(:method ((object list))
object))
Sometimes it can be convenient to define some of the methods along with the defgeneric form. It's more a matter of style, and this gets into the other parts of your question.
Does the :method option present a default, or at least, document what you expect the most common use case will be, or does it have additional semantics?
It can be a sort of default, if you define a method without type specifiers, or with type specifiers that apply to every object (e.g., t).
As a style point, if you expect to define only one method, does it make more sense to define it in the defgeneric form (if you can, indeed, do that), or separately in a defmethod? Or does it not make sense to make a generic function in this case at all, and instead use a regular defun?
I think it depends on why you expect to define only one method. If it's because you're just defining a default, but expect other users to implement methods on it, then putting the methods along with the defmethod might be convenient if anyone needs to find the source. If you expect that there's only one thing to do, then a normal function might make more sense. I think these decisions just come down to style choices.
It's also worth noting that there are other forms that can define methods on a generic function (and other forms that can produce generic functions, too). In the HyperSpec, using the up arrows to go to higher sections will usually bring you to more prose. In this case, 7.6.1 Introduction to Generic Functions is useful:
Some operators define methods for a generic function. These operators will be referred to as method-defining operators; their associated forms are called method-defining forms. The standardized method-defining operators are listed in the next figure.
defgeneric defmethod defclass define-condition defstruct
It's up to personal preference and what how the system would be organized in source. Either
simple generic function: a bunch of DEFMETHODS
complex generic function: a DEFGENERIC
and a bunch of DEFMETHODS
generic function: a DEFGENERIC
and a bunch of methods inside
Most Lisp OO-systems before CLOS used the single method definition form. Code could get too long in one form otherwise, generic functions mostly did not exist, ...
With class-oriented single-dispatch systems it could have made sense to organize methods in a class definition. With the introduction of generic functions and multiple dispatch it made sense to organize them under a generic function definition.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With