Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use of :method option in defgeneric

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 defmethods. 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?

like image 461
amp108 Avatar asked Apr 15 '15 00:04

amp108


2 Answers

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
like image 176
Joshua Taylor Avatar answered Nov 09 '22 17:11

Joshua Taylor


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.

like image 22
Rainer Joswig Avatar answered Nov 09 '22 18:11

Rainer Joswig