From: Joris Bleys
Subject: call-next-method weirdness
Date: 
Message-ID: <pan.2004.07.14.16.13.05.613942@nomasp.vub.ac.be>
Hello everyone reading this,

I'm having troubles creating more specific methods which should call
the less specific methods as well.

For instance:

- file: category.lisp

(class category (some-general-superclass)
  (.. slots ..)
  (:documentation "You know ..."))

(defgeneric cat-merge ((cat1 category) (cat2 category))
  (:documentation "Some useful nonsense."))

(defmethod cat-merge ((cat1 category) (cat2 category))
  (.. adapt some of the slots of cat1 ..))

- file: prototype-category.lisp

(class prototype-category (category)
  (.. slots ..)
  (:documentation "Sigh."))

(defmethod cat-merge ((procat1 prototype-category)
                      (procat2 prototype-category))
  (.. adapt some prototype-specific slots of cat1)
  (call-next-method))

Both files are loaded:

  (load "category.lisp")
  (load "prototype-category.lisp")

*First question*

Lisp generates a warning:

Warning: (METHOD CAT-MERGE (CATEGORY CATEGORY)), :OPERATOR was defined in
         category.lisp and is now being defined in prototype-category.lisp

I guess I know what it tries to tell me, but in what way can I circumvent
this?

*Second question*

Calling cat-merge using two prototype-categories as parameters generates
an error, probably because the cat-merge for two normal categories is lost.

Error: No next method for method #<STANDARD-METHOD CAT-MERGE (CATEGORY 
       CATEGORY)> of generic function #<STANDARD-GENERIC-FUNCTION CAT-MERGE>
       with args (#<PROTOTYPE-CATEGORY @ #x71bcf14a> #<PROTOTYPE-CATEGORY
       @ #x71be922a>)
  [condition type: PROGRAM-ERROR]

Reinterpreting the definition of cat-merge in category.lisp resolves my
problem. How can I make it work without the hassle ?

Many thanks in advance,

Joris

From: Pascal Costanza
Subject: Re: call-next-method weirdness
Date: 
Message-ID: <cd3njh$hmq$1@newsreader2.netcologne.de>
Joris Bleys wrote:

> Hello everyone reading this,
> 
> I'm having troubles creating more specific methods which should call
> the less specific methods as well.

The following code has some problems, but it shouldn't generate the 
problem describe. It seems to me that you have changed some definitions 
in order to produce this description. Here are some comments:

> For instance:
> 
> - file: category.lisp
> 
> (class category (some-general-superclass)
>   (.. slots ..)
>   (:documentation "You know ..."))

-> defclass

> (defgeneric cat-merge ((cat1 category) (cat2 category))
>   (:documentation "Some useful nonsense."))

generic functions are not specialized, so you can't say here that cat1 
and cat2 are specialized on class category. Instead, say (defgeneric 
cat-merge (cat1 cat2) ...)

> (defmethod cat-merge ((cat1 category) (cat2 category))
>   (.. adapt some of the slots of cat1 ..))
> 
> - file: prototype-category.lisp
> 
> (class prototype-category (category)
>   (.. slots ..)
>   (:documentation "Sigh."))
> 
> (defmethod cat-merge ((procat1 prototype-category)
>                       (procat2 prototype-category))
>   (.. adapt some prototype-specific slots of cat1)
>   (call-next-method))
> 
> Both files are loaded:
> 
>   (load "category.lisp")
>   (load "prototype-category.lisp")
> 
> *First question*
> 
> Lisp generates a warning:
> 
> Warning: (METHOD CAT-MERGE (CATEGORY CATEGORY)), :OPERATOR was defined in
>          category.lisp and is now being defined in prototype-category.lisp

This can only happen when the new method indeed redefines an existing 
method as defined in another file. One method definition replaces 
another one only when they are specialized on the same classes or eql 
specializers. Otherwise, they are considered to be different.

> I guess I know what it tries to tell me, but in what way can I circumvent
> this?
> 
> *Second question*
> 
> Calling cat-merge using two prototype-categories as parameters generates
> an error, probably because the cat-merge for two normal categories is lost.
> 
> Error: No next method for method #<STANDARD-METHOD CAT-MERGE (CATEGORY 
>        CATEGORY)> of generic function #<STANDARD-GENERIC-FUNCTION CAT-MERGE>
>        with args (#<PROTOTYPE-CATEGORY @ #x71bcf14a> #<PROTOTYPE-CATEGORY
>        @ #x71be922a>)
>   [condition type: PROGRAM-ERROR]
> 
> Reinterpreting the definition of cat-merge in category.lisp resolves my
> problem. How can I make it work without the hassle ?

You should check again whether you have a method definition for 
(category category) in the new file.


Pascal

-- 
Tyler: "How's that working out for you?"
Jack: "Great."
Tyler: "Keep it up, then."
From: Joris Bleys
Subject: Re: call-next-method weirdness
Date: 
Message-ID: <2d51d2ef.0407150543.1f6ae0e1@posting.google.com>
Pascal Costanza <········@web.de> wrote in message news:<············@newsreader2.netcologne.de>...
> Joris Bleys wrote:
> 
> > Hello everyone reading this,
> > 
> > I'm having troubles creating more specific methods which should call
> > the less specific methods as well.
> 
> The following code has some problems, but it shouldn't generate the 
> problem describe. It seems to me that you have changed some definitions 
> in order to produce this description. Here are some comments:
> 
> > For instance:
> > 
> > - file: category.lisp
> > 
> > (class category (some-general-superclass)
> >   (.. slots ..)
> >   (:documentation "You know ..."))
> 
> -> defclass
> 
> > (defgeneric cat-merge ((cat1 category) (cat2 category))
> >   (:documentation "Some useful nonsense."))
> 
> generic functions are not specialized, so you can't say here that cat1 
> and cat2 are specialized on class category. Instead, say (defgeneric 
> cat-merge (cat1 cat2) ...)
> 
> > (defmethod cat-merge ((cat1 category) (cat2 category))
> >   (.. adapt some of the slots of cat1 ..))
> > 
> > - file: prototype-category.lisp
> > 
> > (class prototype-category (category)
> >   (.. slots ..)
> >   (:documentation "Sigh."))
> > 
> > (defmethod cat-merge ((procat1 prototype-category)
> >                       (procat2 prototype-category))
> >   (.. adapt some prototype-specific slots of cat1)
> >   (call-next-method))
> > 
> > Both files are loaded:
> > 
> >   (load "category.lisp")
> >   (load "prototype-category.lisp")
> > 
> > *First question*
> > 
> > Lisp generates a warning:
> > 
> > Warning: (METHOD CAT-MERGE (CATEGORY CATEGORY)), :OPERATOR was defined in
> >          category.lisp and is now being defined in prototype-category.lisp
> 
> This can only happen when the new method indeed redefines an existing 
> method as defined in another file. One method definition replaces 
> another one only when they are specialized on the same classes or eql 
> specializers. Otherwise, they are considered to be different.
> 
> > I guess I know what it tries to tell me, but in what way can I circumvent
> > this?
> > 
> > *Second question*
> > 
> > Calling cat-merge using two prototype-categories as parameters generates
> > an error, probably because the cat-merge for two normal categories is lost.
> > 
> > Error: No next method for method #<STANDARD-METHOD CAT-MERGE (CATEGORY 
> >        CATEGORY)> of generic function #<STANDARD-GENERIC-FUNCTION CAT-MERGE>
> >        with args (#<PROTOTYPE-CATEGORY @ #x71bcf14a> #<PROTOTYPE-CATEGORY
> >        @ #x71be922a>)
> >   [condition type: PROGRAM-ERROR]
> > 
> > Reinterpreting the definition of cat-merge in category.lisp resolves my
> > problem. How can I make it work without the hassle ?
> 
> You should check again whether you have a method definition for 
> (category category) in the new file.
> 
> 
> Pascal

Ok, thanks, I found it moments after I posted my message and indeed I
forgot to change the signature of the prototype-category definition.
Maybe I should get more sleep :).

Joris
From: Kenny Tilton
Subject: Re: call-next-method weirdness
Date: 
Message-ID: <XNfJc.77272$a92.17656@twister.nyc.rr.com>
Joris Bleys wrote:
> Hello everyone reading this,
> 
> I'm having troubles creating more specific methods which should call
> the less specific methods as well.
> 
> For instance:
> 
> - file: category.lisp
> 
> (class category (some-general-superclass)
>   (.. slots ..)
>   (:documentation "You know ..."))
> 
> (defgeneric cat-merge ((cat1 category) (cat2 category))
>   (:documentation "Some useful nonsense."))
> 
> (defmethod cat-merge ((cat1 category) (cat2 category))
>   (.. adapt some of the slots of cat1 ..))
> 
> - file: prototype-category.lisp
> 
> (class prototype-category (category)
>   (.. slots ..)
>   (:documentation "Sigh."))
> 
> (defmethod cat-merge ((procat1 prototype-category)
>                       (procat2 prototype-category))
>   (.. adapt some prototype-specific slots of cat1)
>   (call-next-method))
> 
> Both files are loaded:
> 
>   (load "category.lisp")
>   (load "prototype-category.lisp")
> 
> *First question*
> 
> Lisp generates a warning:
> 
> Warning: (METHOD CAT-MERGE (CATEGORY CATEGORY)), :OPERATOR was defined in
>          category.lisp and is now being defined in prototype-category.lisp
> 
> I guess I know what it tries to tell me, but in what way can I circumvent
> this?

My guess is that you cut/pasted the code from category.lisp into 
prototype-category (p-c), saved, then edited p-c.lisp to add 
"prototype-" but did /not/ save, then executed the loads. My second 
guess is a similar scenario in which you managed to leave p-c.lisp with 
definitions for methods for both. Anyway, something like that.

If you are using AllegroCL, it can be set up to save everything, 
recompile, and run-- all with one keychord. Your environment might have 
something similar. (This would help with the first scenario, but not the 
second.)

kt


> 
> *Second question*
> 
> Calling cat-merge using two prototype-categories as parameters generates
> an error, probably because the cat-merge for two normal categories is lost.

Nope. See below.

> 
> Error: No next method for method #<STANDARD-METHOD CAT-MERGE (CATEGORY 
>        CATEGORY)> of generic function #<STANDARD-GENERIC-FUNCTION CAT-MERGE>
>        with args (#<PROTOTYPE-CATEGORY @ #x71bcf14a> #<PROTOTYPE-CATEGORY
>        @ #x71be922a>)
>   [condition type: PROGRAM-ERROR]
> 
> Reinterpreting the definition of cat-merge in category.lisp resolves my
> problem. How can I make it work without the hassle ?

You clearly set up cat-merge for the p-c, added the call-next-method, 
but neglected to change the specializations, then saved. So the first 
warning was telling you you had done that, and that point you created a 
cat-merge specialized on cat-cat which attempted a call-next-method. So 
that cat-merge was not lost, it was calling a non-existent next method.

This happens to me all the time when I get involved with new technology 
-- I make simple goofs which I attribute to some deep mystery in the new 
technology. Eventually I develop confidence in the new tech and can 
interpret warnings/errors a lot better.

In general, resolve any warning you get before proceeding, or at least 
return to the first warning when a second warning/error arises (until 
the first warning is resolved and understood, the second warning might 
be a consequence of the first, so is not worth investigating). My 2.

kt

-- 
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: Thomas Schilling
Subject: Re: call-next-method weirdness
Date: 
Message-ID: <opsa5cvbbatrs3c0@news.CIS.DFN.DE>
Kenny "Detective" Tilton sharp-wittedly ascertained:

> My guess is that you cut/pasted the code from category.lisp into 
> prototype-category (p-c), saved, then edited p-c.lisp to add 
> "prototype-" but did /not/ save, then executed the loads. My second 
> guess is a similar scenario in which you managed to leave p-c.lisp with 
> definitions for methods for both. Anyway, something like that.

Wow. My respect for this astute suspect. I had no clue how this could have 
happend when reading the article. And you found two!

My deep respect. :)

ts
-- 
      ,,
     \../   /  <<< The LISP Effect
    |_\\ _==__
__ | |bb|   | _________________________________________________
From: Kenny Tilton
Subject: Re: call-next-method weirdness
Date: 
Message-ID: <D_DJc.46203$4h7.5412096@twister.nyc.rr.com>
Thomas Schilling wrote:
> 
> Kenny "Detective" Tilton sharp-wittedly ascertained:
> 
>> My guess is that you cut/pasted the code from category.lisp into 
>> prototype-category (p-c), saved, then edited p-c.lisp to add 
>> "prototype-" but did /not/ save, then executed the loads. My second 
>> guess is a similar scenario in which you managed to leave p-c.lisp 
>> with definitions for methods for both. Anyway, something like that.
> 
> 
> Wow. My respect for this astute suspect. I had no clue how this could 
> have happend when reading the article. And you found two!

Elementary, Watson, but as I hinted, only once one has become accustomed 
to what I might have mentioned, which is one of the great qualities of 
Lisp: the warnings/errors generally indicate precisely what has gone wrong.

Where C++ would throw a fit and spew a hundred diagnostics, none of them 
comprehensible or relevant, Lisp in this case nailed the problem on the 
head: the second file was redefining the same method specialization as 
the first. Case closed, except for newbies who are so jaded by the 
uselessness of compiler warnings from other languages that they may 
barely even read the error message.

That was certainly my case Before Lisp. I always got a kick out of it 
when debugging in other languages when, after hours of investigation I 
finally found the problem, and it turned out that in this one case the 
error message (a runtime error) turned out to have actually described 
the problem! That happened so rarely i generally considered error 
messages to rule out whatever was being claimed as the problem. 
"Insufficient privilege? OK, we know it's not that." But to be honest I 
generally never even read the stuff, I just looked at the call stack and 
went from there.

Before our most recent Lisp-NYC meeting degenerated into an 
embarrassment for most of the Upper West Side of Manhattan, a newbie was 
asking how Lisp could be sold to management. If he survived the night, I 
plan to follow-up with this point: it's not one huge thing, it's a 
hundred little things. Like meaningful warnings.

kt

-- 
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: Thomas Schilling
Subject: Re: call-next-method weirdness
Date: 
Message-ID: <opsa7fg7tftrs3c0@news.CIS.DFN.DE>
Kenny Tilton wrote:
>
> Thomas Schilling wrote:
>>
>> Kenny "Detective" Tilton sharp-wittedly ascertained:
>>
>>> My guess is that you cut/pasted the code from category.lisp into 
>>> prototype-category (p-c), saved, then edited p-c.lisp to add 
>>> "prototype-" but did /not/ save, then executed the loads. My second 
>>> guess is a similar scenario in which you managed to leave p-c.lisp 
>>> with definitions for methods for both. Anyway, something like that.
>>
>>
>> Wow. My respect for this astute suspect. I had no clue how this could 
>> have happend when reading the article. And you found two!
>
> Elementary, Watson, but as I hinted, only once one has become accustomed 
> to what I might have mentioned, which is one of the great qualities of 
> Lisp: the warnings/errors generally indicate precisely what has gone 
> wrong.

I was more refering to the case how this special scenario could have 
happened. Okay, I must admit I didn't give it a serious shot, but I was 
nevertheless impressed how you could reconstruct what must have happened.

> Where C++ would throw a fit and spew a hundred diagnostics, none of them 
> comprehensible or relevant, Lisp in this case nailed the problem on the 
> head: the second file was redefining the same method specialization as 
> the first. Case closed, except for newbies who are so jaded by the 
> uselessness of compiler warnings from other languages that they may 
> barely even read the error message.
>
> That was certainly my case Before Lisp. I always got a kick out of it 
> when debugging in other languages when, after hours of investigation I 
> finally found the problem, and it turned out that in this one case the 
> error message (a runtime error) turned out to have actually described 
> the problem! That happened so rarely i generally considered error 
> messages to rule out whatever was being claimed as the problem. 
> "Insufficient privilege? OK, we know it's not that." But to be honest I 
> generally never even read the stuff, I just looked at the call stack and 
> went from there.

Indeed. I used C++ a lot Before Lisp. And I really hated the way errors 
were reported. Even simple syntax errors. Hence one of my main goals for 
my personal c++ parser were nice error messages, but I found that this is 
especially hard with an ugly language like c++. Ok, but it's history now.

Fortunately, I had some programming break before starting with lisp (ok, I 
got introduced to Prolog in the meantime) so that I wasn't spoiled so much 
by c++ that time. I really appreciate this feature. Though, I still have 
hard times while debugging. The day I was writing, I was hunting some ugly 
bugs, and it wasn't a nice time doing so. Even the backtrace wasn't of 
much use. Admittedly a lot of the problems we have today are due to 
insufficient planning before starting the project. Surely also because the 
project was started by non-programmers. Or, say, no _real_ programmers. 
Furthermore we're doing a lot of GUI-stuff which also is hard to debug I 
think. OTOH, we're now going for version 1 and we'll do the cleanup when 
we're heading for version 2 (I hope).

> Before our most recent Lisp-NYC meeting degenerated into an 
> embarrassment for most of the Upper West Side of Manhattan, a newbie was 
> asking how Lisp could be sold to management. If he survived the night, I 
> plan to follow-up with this point: it's not one huge thing, it's a 
> hundred little things. Like meaningful warnings.

Personally, I'm not so much a fan of bug hunting. (Okay, I mean the 
frustating part.) It's more that I always have more ideas than I can 
implement. Which leads to me having at least 5 (personal) projects running 
at the same time. (But I think it's getting better now. :)

ts
-- 
      ,,
     \../   /  <<< The LISP Effect
    |_\\ _==__
__ | |bb|   | _________________________________________________
From: Barry Margolin
Subject: Re: call-next-method weirdness
Date: 
Message-ID: <barmar-5E2F95.04401220072004@comcast.dca.giganews.com>
In article <················@news.CIS.DFN.DE>,
 Thomas Schilling <······@yahoo.de> wrote:

> Kenny Tilton wrote:
> >
> > Thomas Schilling wrote:
> >>
> >> Kenny "Detective" Tilton sharp-wittedly ascertained:
> >>
> >>> My guess is that you cut/pasted the code from category.lisp into 
> >>> prototype-category (p-c), saved, then edited p-c.lisp to add 
> >>> "prototype-" but did /not/ save, then executed the loads. My second 
> >>> guess is a similar scenario in which you managed to leave p-c.lisp 
> >>> with definitions for methods for both. Anyway, something like that.
> >>
> >>
> >> Wow. My respect for this astute suspect. I had no clue how this could 
> >> have happend when reading the article. And you found two!
> >
> > Elementary, Watson, but as I hinted, only once one has become accustomed 
> > to what I might have mentioned, which is one of the great qualities of 
> > Lisp: the warnings/errors generally indicate precisely what has gone 
> > wrong.
> 
> I was more refering to the case how this special scenario could have 
> happened. Okay, I must admit I didn't give it a serious shot, but I was 
> nevertheless impressed how you could reconstruct what must have happened.

It's easy to appear to be psychic when you've been on Usenet for ages 
and have seen just about every silly mistake before.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Joe Marshall
Subject: Re: call-next-method weirdness
Date: 
Message-ID: <ekn6sqak.fsf@ccs.neu.edu>
Barry Margolin <······@alum.mit.edu> writes:

> It's easy to appear to be psychic when you've been on Usenet for ages 
> and have seen just about every silly mistake before.

When I was TA'ing a Lisp course, one problem set involved doing
polynomial arithmetic using lists.  Lists had just been introduced, so
there was a lot of typical confusion about CONS, LIST, and APPEND.

One student came up to me and said that his code didn't work. (You'd
think this was a given.  People rarely ask the TA for help when things
work.)  He explained that polynomial division worked for monomials,
but got an error for anything more complicated.  

I asked ``Did you write a routine called something like
PARTIAL-DIVIDE?''

He said, ``Yes... ''

I said ``In that routine, you are calling CONS to accumulate the
answer and you should be calling LIST.''

He gave me this look, went back to his code and returned a minute
later.  He said ``That was it!''  I'm pretty sure he thought I must
have been psychic.
From: Barry Margolin
Subject: Re: call-next-method weirdness
Date: 
Message-ID: <barmar-FD1932.12451020072004@comcast.dca.giganews.com>
In article <············@ccs.neu.edu>, Joe Marshall <···@ccs.neu.edu> 
wrote:

> Barry Margolin <······@alum.mit.edu> writes:
> 
> > It's easy to appear to be psychic when you've been on Usenet for ages 
> > and have seen just about every silly mistake before.
> 
> When I was TA'ing a Lisp course, one problem set involved doing
> polynomial arithmetic using lists.  Lists had just been introduced, so
> there was a lot of typical confusion about CONS, LIST, and APPEND.
> 
> One student came up to me and said that his code didn't work. (You'd
> think this was a given.  People rarely ask the TA for help when things
> work.)  He explained that polynomial division worked for monomials,
> but got an error for anything more complicated.  
> 
> I asked ``Did you write a routine called something like
> PARTIAL-DIVIDE?''
> 
> He said, ``Yes... ''
> 
> I said ``In that routine, you are calling CONS to accumulate the
> answer and you should be calling LIST.''
> 
> He gave me this look, went back to his code and returned a minute
> later.  He said ``That was it!''  I'm pretty sure he thought I must
> have been psychic.

I've pulled it off numerous times on comp.unix.programmer.  One of the 
easiest ones is when they write something like:

  if (sock_fd = connect(...) == -1) {
    /* do stuff with sock_fd */
  }

Since == binds more tightly than =, this sets sock_fd to the result of 
the comparison rather than the socket that was opened (to use the idiom 
properly, you have to parenthesize the assignment portion of the 
expression).  I can tell this is what they did wrong as soon as they 
mention that they got a "Socket operation on non-socket" error; this 
saves lots of time because newbies rarely think to post code when 
they're asking for help. :)

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Joris Bleys
Subject: Re: call-next-method weirdness
Date: 
Message-ID: <2d51d2ef.0407150545.7aaa9785@posting.google.com>
Thanks a lot for helping me. I found what you suspected moments after
I cried out for help. You're a great debugger !!

Joris