GOOPS generic functions and accessors often have short, generic names.
For example, if a vector package provides an accessor for the X
coordinate of a vector, that accessor may just be called
doesn’t need to be called, for example,
GOOPS will work out, when it sees code like
(x obj), that
the vector-specific method of
x should be called if obj is
That raises the question, though, of what happens when different
packages define a generic function with the same name. Suppose we work
with a graphical package which needs to use two independent vector
packages for 2D and 3D vectors respectively. If both packages export
x, what does the code using those packages end up with?
duplicate binding handlers explains how
this is resolved for conflicting bindings in general. For generics,
there is a special duplicates handler,
tells the module system to merge generic functions with the same name.
Here is an example:
(define-module (math 2D-vectors) #:use-module (oop goops) #:export (x y ...)) (define-module (math 3D-vectors) #:use-module (oop goops) #:export (x y z ...)) (define-module (my-module) #:use-module (oop goops) #:use-module (math 2D-vectors) #:use-module (math 3D-vectors) #:duplicates (merge-generics))
The generic function
(my-module) will now incorporate
all of the methods of
x from both imported modules.
To be precise, there will now be three distinct generic functions named
(my-module); and these functions
share their methods in an interesting and dynamic way.
To explain, let’s call the imported generic functions (in
(math 3D-vectors)) the ancestors, and the
merged generic function (in
(my-module)), the descendant.
The general rule is that for any generic function G, the applicable
methods are selected from the union of the methods of G’s descendant
functions, the methods of G itself and the methods of G’s ancestor
Thus ancestor functions effectively share methods with their
descendants, and vice versa. In the example above,
(math 2D-vectors) will share the methods of
(my-module) and vice versa.32 Sharing is
dynamic, so adding another new method to a descendant implies adding it
to that descendant’s ancestors too.
But note that
(math 2D-vectors) doesn’t share methods with
(math 3D-vectors), so modularity is still preserved.