From: Peter Seibel
Subject: Re: defgeneric, defstruct and no CLOS
Date: 
Message-ID: <m2oe52948f.fsf@gigamonkeys.com>
verec <·····@mac.com> writes:

> Obviously, I can define:
> (defun load-dict (dict-name) ...)
> and
> (defun load-grid (grid-name) ...)
>
> But that "noise in my head" I was referring to above is nagging
> me, and claims loudly to my hears: "This is crap! What you want
> is: (defun load (grid) ... ) and (defun load (dict) ...)"
>
> So, my question realy is, assuming both:
> (defstruct grid ...) and
> (defstruct dict ...)
>
> how would I go about
>
> (defun load (grid) ... ) and
>
> (defun load (dict) ... ) and while I'm there, not shadow the
>
> standard cl::load ?

I think you're life will get better if you separate the two problems
you're wrestling with. One is how to define generic functions so that
you can use the same name for different (but related) operations,
depending on the type of the objects to which you apply the
operation. The other is what to do when you want to use a name that is
the same as a symbol exported from the COMMON-LISP package.

To solve the first problem you indeed define a generic function:

  (defgeneric load-from-disk (thing source)
    (:documentation "Populate THING with data from SOURCE."))

  (defmethod load-from-disk ((thing grid) (source stream)) ...)

  (defmethod load-from-disk ((thing dict) (source stream)) ...)

To solve the second problem you either bite the bullet and define your
own package in which you shadow the name you want to use (e.g. LOAD)
or decide that you can live with a different name. In general it's
probably a bad idea to shadow a symbol from the COMMON-LISP package
just to use a name--sometimes it's appropriate if you actually want to
replace the functionality of the function (or whatever) named by the
symbol in the COMMON-LISP pacakge. For instance, if you were working
on a system where you wanted every function definition to squirrel
away some extra info, you might shadow DEFUN and define your own macro
that expanded into a CL:DEFUN form plus some other bits.

> This suggests using packages as a means of encapsulation
> but that little voice is not too happy with that idea either.

Packages aren't for encapsulation--they're for managing namespaces.

> If this kind of "overloading" is not "the Lisp way" then that's
> fine with me too, but what would be "the Lisp way" in that case?

Use a different name. This is sometimes annoying but there it is.

> The thing is, I've got quite a few "generic" verbs that I'd like to
> apply to any ``object''. In that example, and assuming that
> overloading can be made to work (and is "idiomatic"), I'd add to the
> party:
>
> (defun locate (grid x y)
> 	"Returns the word limit associated with coordinates
> 	x and y of the grid"
>       ... )
>
> and
>
> (defun locate (dict word)
> 	"Returns the index of the word if found, or the one's complement
>  	of the index this word would need to be inserted at if not
>  	found"
> 	...)
> 
> In short: how can I make this overloading work, or, what would be a
> better (more idiomatic) alternative?

For this, since there's no LOCATE in the COMMON-LISP package you just
need to use DEFGENERIC and DEFMETHOD.

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/