#36 handle CLOS warnings in a CLOSy way




There is a reason, of course, but it is not in ANSI nor AMOP, because
these standards hardly address the issues of a development environment.

Both warnings are hints that something is wrong with the source code.

1) *warn-if-gf-already-called*
It's a hint that the order in which program files are loaded (order
of definitions, order of macro expansions, or similar) is wrong.

(defclass ware () ())
(defclass book (ware) ())
(defclass cd (ware) ())
(defclass dvd (ware) ())
(defgeneric add-to-inventory (object))
(defmethod add-to-inventory ((object ware)) nil)
(defvar *bible* (make-instance 'book))
(add-to-inventory *bible*)
(defvar *book-counter* 0)
(defmethod add-to-inventory ((object book)) (incf *book-counter*))
(defvar *harry-potter-7* (make-instance 'book))
(add-to-inventory *harry-potter-7*)
*book-counter* => 1

Since the bible and the harry-potter book were already added to the
inventory, the programmer might have expected that *book-counter* is 2.

2) *gf-warn-on-replacing-method*
It's a hint that different parts of the program, possibly developed
by independent people, are colliding.

Example: same code as above, then additionally:
(defgeneric sell (object price))
(defvar *book-sales-statistics* (make-hash-table))
(defmethod add-to-inventory ((object book))
(let ((stat (gethash (book-title book) *book-sales-statistics*)))
(unless stat (setf stat (make-stat)))
(stat-add stat 1 price)
(setf (gethash (book-title book) *book-sales-statistics*) stat)))

The programmer who programmed the first add-to-inventory@book
method expects that *book-counter* will be incremented. The programmer
who programmed the second add-to-inventory@book method expects
that *book-sales-statistics* gets augmented. If the implementation
gives no warning, one of the two programmers will waste time debugging.

That was the pragmatic, development-driven reasoning. The theoretical
reasoning behind it is as follows:

1) *warn-if-gf-already-called*
A generic function is defined by a contract. Whoever puts a method on a
GF, however, is also expecting a contract to be fulfilled. (In the
example above, it is that *book-counter* equals the number of invocations
of add-to-inventory on book instances.)
If the GF was already called before the method was installed, the
method's contract was definitely broken. Maybe the programmer has
foreseen this case (in this example: he could initialize *book-counter*
to the number of instances of book that exist at this moment, rather
than to 0), or maybe not. This is what the warning is about.

2) *gf-warn-on-replacing-method*
This warning can be warranted for the same reason as 1): If the old
method and the new method have a different contract, something is fishy
and possibly wrong, as in 1).
Additionally, the programmers may not even have intended to replace the
method. They may have intended cumulative effects of the two methods.

Of course, there are GFs, like PRINT-OBJECT, for which particular methods
have no different contract than the GF contract. On these GFs, the warnings
are pointless. But these GFs are a minority.



  • Sam Steingold

    Sam Steingold - 2007-11-23
    • status: open --> closed-fixed
  • Sam Steingold

    Sam Steingold - 2007-11-23

    Logged In: YES
    Originator: YES

    Thanks for the suggestion - it has been just implemented and
    checked into the CVS repository, and will be available in the next
    If you cannot wait for the next release, you can get the latest
    development sources from the CVS and compile them yourself.
    Please be aware that the development sources are not stable and
    might not even compile on your machine.
    You should report any problems you encounter with the CVS sources
    to the <clisp-devel> mailing list, not to the <clisp-list>.
    If you use the CVS sources, you should read <clisp-devel>
    since the CVS log goes there.


Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

No, thanks