[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: where to put generics?
Re: where to put generics?
Mon, 14 Jul 2003 18:42:35 +0200
Gnus/5.1002 (Gnus v5.10.2) Emacs/21.3 (gnu/linux)
Andy Wingo <address@hidden> writes:
> I figured while I was emailing I could get something else off my chest
> -- what is the best way for two modules that do not want to know about
> each other to add methods to the same generic? The problem there is that
> such a generic might not exist in the 'stock' top-level environment. The
> generic would need to be created and then exported, but only one time --
> if both modules export generics, the generics from recent modules will
> replace those from previous modules.
> So, if the generics are only exported once, where should they be put?
> I'm hacking around this for the moment by putting them in the root
> module, but that's not exactly an elegant solution. What's the thought
> on this? Has anyone else had to deal with these issues in the past?
Firstly, Gregor Kiczales, the author of CLOS, has discussed issues
related to this in his paper "Issues In the Design and Specification
of Class Libraries", OOPSLA92
(http://kvast.blakulla.net/mdj/kiczales92.pdf). It is a very
elucidating read. The way to think about it is that a module is
publishing an interface with certain functionality and a generic
function can be used to provide part of this functionality. If one
follows certain rules listed in his paper when extending generic
functions, most problems will disappear.
Secondly, I've made an attempt at another kind of solution. Let's
assume that module A exports a generic foo which both modules B and C
want to add methods to, but B don't want to be confused by C's methods
and vice versa. You can then do this:
(define-method (foo ...) ...) (1)
:use-module ((A) :prefix A:))
(define-extended-generic foo A:foo)
(define-method (foo ...) ...) (2)
and a similar code for module C.
The extended generic function foo becomes a descendant of A:foo and
A:foo becomes an ancestor of foo, but they are still distinct generic
functions. Methods added to foo in module B will belong to foo only,
but can be accessed from all descendants and ancestors. Conversely,
any generic function can access the methods added to all of its
descendants and ancestors. This means that module A can run methods
from modules B and C, while B and C won't be able to access
The second operand of define-extended-generic can also be a list of
generic functions. This can be used to "merge" generic functions from
different modules. There is also a recent addition to the module
system which can do this automagically. Search for "merge-generics"
in the NEWS file.