From: Jeff
Subject: Purpose of defmethod
Date: 
Message-ID: <xUcIc.52250$JR4.8471@attbi_s54>
I'm trying to understand the purpose of having defmethod. When I began
learning the CLOS, I just assumed that defmethod was used to create
methods for classes. However, now that I've been using it (a little
while), I can't seem to understand how it is different from any other
defun. Take the following example:

(defclass shape ())
(defclass square (shape) ((x :initform 1 :accessor side)))

Now, we'll create a couple methods:

(defmethod area ((s shape)) 0)
(defmethod area ((s square)) (sq (side square)))

Aside from being able to declare an argument that is a class, how are
these different from any other defun? Why even have defmethod? It just
appears to be a macro that does everything that defun can and more. So
why shouldn't I just use defmethod /everywhere/ instead of defun?

I'm sure I'm just misunderstanding something simple, or am missing a
small piece of the puzzle where I'll say "ahh, ok!" once I have it. Any
help on this is appreciated! Thanks in advance!

Jeff

From: Pascal Bourguignon
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <87vfgubm09.fsf@thalassa.informatimago.com>
"Jeff" <···@mfire.com> writes:

> I'm trying to understand the purpose of having defmethod. When I began
> learning the CLOS, I just assumed that defmethod was used to create
> methods for classes. However, now that I've been using it (a little
> while), I can't seem to understand how it is different from any other
> defun. Take the following example:
> 
> (defclass shape ())
> (defclass square (shape) ((x :initform 1 :accessor side)))
> 
> Now, we'll create a couple methods:
> 
> (defmethod area ((s shape)) 0)
> (defmethod area ((s square)) (sq (side square)))
> 
> Aside from being able to declare an argument that is a class, how are
> these different from any other defun? Why even have defmethod? It just
> appears to be a macro that does everything that defun can and more. So
> why shouldn't I just use defmethod /everywhere/ instead of defun?
> 
> I'm sure I'm just misunderstanding something simple, or am missing a
> small piece of the puzzle where I'll say "ahh, ok!" once I have it. Any
> help on this is appreciated! Thanks in advance!

Are you joking?

(defun f-area (stuff)
  (typecase stuff
    (shape 0)
    (square (sq (side square)))))

vs.

(defmethod area ((s shape)) 0)
(defmethod area ((s square)) (sq (side square)))

?

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

There is no worse tyranny than to force a man to pay for what he does not
want merely because you think it would be good for him. -- Robert Heinlein
From: Raistlin Magere
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <ccroeu$o10$1@news.ox.ac.uk>
"Pascal Bourguignon" <····@thalassa.informatimago.com> wrote in message
···················@thalassa.informatimago.com...
> "Jeff" <···@mfire.com> writes:
>
>
> Are you joking?
>
> (defun f-area (stuff)
>   (typecase stuff
>     (shape 0)
>     (square (sq (side square)))))
>
> vs.
>
> (defmethod area ((s shape)) 0)
> (defmethod area ((s square)) (sq (side square)))
>
> ?
>

I think what the OP meant was: what is the point of defun?, why not just
replace defun with (defmethod name ((variable t)) code) - a bit like what's
the point of defstruct given that we have defclass.
From: Thomas Schilling
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <opsazdwcgatrs3c0@news.CIS.DFN.DE>
Raistlin Magere wrote:
> "Pascal Bourguignon" <····@thalassa.informatimago.com> wrote in message
> ···················@thalassa.informatimago.com...
>> "Jeff" <···@mfire.com> writes:
>>
>>
>> Are you joking?
>>
>> (defun f-area (stuff)
>>   (typecase stuff
>>     (shape 0)
>>     (square (sq (side square)))))
>>
>> vs.
>>
>> (defmethod area ((s shape)) 0)
>> (defmethod area ((s square)) (sq (side square)))
>>
>> ?
>>
>
> I think what the OP meant was: what is the point of defun?, why not just
> replace defun with (defmethod name ((variable t)) code) - a bit like 
> what's
> the point of defstruct given that we have defclass.

efficiency?

-- 
      ,,
     \../   /  <<< The LISP Effect
    |_\\ _==__
__ | |bb|   | _________________________________________________
From: Antonio Menezes Leitao
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <87k6xa4e1h.fsf@evaluator.pt>
Thomas Schilling <······@yahoo.de> writes:

> Raistlin Magere wrote:
>> "Pascal Bourguignon" <····@thalassa.informatimago.com> wrote in message
>> ···················@thalassa.informatimago.com...
>>> "Jeff" <···@mfire.com> writes:
>>>
>>>
>>> Are you joking?
>>>
>>> (defun f-area (stuff)
>>>   (typecase stuff
>>>     (shape 0)
>>>     (square (sq (side square)))))
>>>
>>> vs.
>>>
>>> (defmethod area ((s shape)) 0)
>>> (defmethod area ((s square)) (sq (side square)))
>>>
>>> ?
>>>
>>
>> I think what the OP meant was: what is the point of defun?, why not just
>> replace defun with (defmethod name ((variable t)) code) - a bit like
>> what's
>> the point of defstruct given that we have defclass.
>
> efficiency?

I remember reading one of the first papers about CLOS (can't remember
the name or the author) where they claimed that a generic function
containing only a non-specialized method should have the same
performance as a defun and, if I'm not mistaken, the idea was to
reimplement defun as a macro expanding into such defmethod.

I wish I could find that paper...

Ant�nio Leit�o.
From: Barry Margolin
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <barmar-F89B75.04294520072004@comcast.dca.giganews.com>
In article <··············@evaluator.pt>,
 Antonio Menezes Leitao <··············@evaluator.pt> wrote:

> I remember reading one of the first papers about CLOS (can't remember
> the name or the author) where they claimed that a generic function
> containing only a non-specialized method should have the same
> performance as a defun and, if I'm not mistaken, the idea was to
> reimplement defun as a macro expanding into such defmethod.

This is a theoretical possibility, but may be difficult to achieve in 
many implementations.

However, to get back to the original question, I like to think of it as 
similar to the question of why we still have SETQ when SETF can always 
be used in its place.  I see a few justifications:

1. Historical.  The predecessor Lisps that CL evolved from all had SETQ 
and DEFUN, and CL was intended to be mostly upward compatible with those 
Lisps.  Removing these from the language was simply too severe a change.  
And don't forget that CLOS was a late addition to the language -- it 
wasn't adopted until long after CLtL1 was published.  Such an 
incompatible change between CLtL1 and ANSI CL was way outside the 
charter of the ANSI committee.

2. Declarative clarity.  When SETF or DEFMETHOD are used, the reader is 
immediately alerted that something more general than a simple variable 
assignment or function definition is being done.  In the case of SETF 
they'll be prepared to look for a generic place being assigned.  In the 
case of DEFMETHOD, they'll be clued in to the fact that a generic 
function is being augmented.  Using the more general mechanisms when the 
simpler ones would work adds cognitive load to future readers and 
maintainers of the program.

3. Bootstrapping.  CLOS was designed so that it could mostly be 
implemented in CL -- many CL implementations adopted the PCL (Portable 
Common LOOPS) implementation of CLOS.  This needs a lower-level 
interface to implement the underlying functions.  I suppose it could all 
be done with (setf (symbol-function ...) #'(lambda ...)), but this is a 
bit crude and DEFUN has always been there to serve this purpose.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Pascal Costanza
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <ccsdd2$930$1@newsreader2.netcologne.de>
Thomas Schilling wrote:

>> I think what the OP meant was: what is the point of defun?, why not
>> just replace defun with (defmethod name ((variable t)) code) - a
>> bit like what's the point of defstruct given that we have defclass.
> 
> efficiency?

No, efficiency is really not the main point. As Antonio said, if there's 
only one method defined on a generic function, the efficiency should be 
the same for both cases. You can declare defunned functions as inline 
functions which you cannot do for generic functions, but I don't think 
even that would have convinced the CL designers to keep defun because 
they regularly used the rationale for other design decisions that clever 
compilers can do wonders. (Richard Gabriel says something about these 
things in a paper criticizing Common Lisp.)

In my opinion, one of they key points of a defun is that it is closed, 
in the sense that you cannot add (or remove) methods, whereas generic 
functions can be altered even at runtime. This is sometimes desirable 
and, IIRC, is why Dylan added sealing to its language.


Pascal

-- 
Tyler: "How's that working out for you?"
Jack: "Great."
Tyler: "Keep it up, then."
From: Tim Bradshaw
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <fbc0f5d1.0407120237.5e621699@posting.google.com>
Pascal Costanza <········@web.de> wrote in message news:<············@newsreader2.netcologne.de>...
> 
> No, efficiency is really not the main point. As Antonio said, if there's 
> only one method defined on a generic function, the efficiency should be 
> the same for both cases.

No, that's not at all clear.  A function can be compiled extremely
efficiently, and it's hard to see that this can be done for GFs
without additional features in the language.  Consider something like
(in the same file);

(defun foo (...) ...)

(defun bar (...) ... (foo ...) ...)

The call to FOO can make all sorts of assumptions: in particular it
can assume that the FOO being called is the definition in the same
file, and do all sorts of inference about types, and shortcut the call
and so on and so on.

I don't think an equivalent GF call can realistically be optimised to
that degree: since new methods can be defined (and existing ones
redefined) there really has to be some indirection there.  There is a
`heroic compiler' argument that a compiler can simply notice all the
callers, and recompile them on change, but that's, well, heroic.  The
other solution is some sort of sealing, so you can declare that the GF
is `finished' in some way, and callers can make assumptions based on
that.  But CL doesn't have that.

> You can declare defunned functions as inline 
> functions which you cannot do for generic functions, but I don't think 
> even that would have convinced the CL designers to keep defun because 
> they regularly used the rationale for other design decisions that clever 
> compilers can do wonders. (Richard Gabriel says something about these 
> things in a paper criticizing Common Lisp.)

Can you quote places in the spec where the `sufficiently smart
compiler' argument is used (or needs to be used)?  I'm aware that
these arguments were around, but the language as eventually defined
seems, to me, not to rely on them very much.  In particular it doesn't
have too many constructs requiring heroic work to make efficient I
think and where it does have such constructs it generally provides
less-heroic but less-functional variants (DEFCLASS vs DEFSTRUCT, GFs
vs plain functions, and so on).  Some parts of the language which I
suspect were seen as too hard to do without heroic techniques were
simply omitted from the spec (the MOP, the environment introspection
stuff).

--tim
From: Pascal Costanza
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <cctuaq$r6q$1@f1node01.rhrz.uni-bonn.de>
Tim Bradshaw wrote:
> Pascal Costanza <········@web.de> wrote in message news:<············@newsreader2.netcologne.de>...
> 
>>No, efficiency is really not the main point. As Antonio said, if there's 
>>only one method defined on a generic function, the efficiency should be 
>>the same for both cases.
> 
> No, that's not at all clear.  A function can be compiled extremely
> efficiently, and it's hard to see that this can be done for GFs
> without additional features in the language.

OK, you're right.

> I don't think an equivalent GF call can realistically be optimised to
> that degree: since new methods can be defined (and existing ones
> redefined) there really has to be some indirection there.  There is a
> `heroic compiler' argument that a compiler can simply notice all the
> callers, and recompile them on change, but that's, well, heroic.  The
> other solution is some sort of sealing, so you can declare that the GF
> is `finished' in some way, and callers can make assumptions based on
> that.  But CL doesn't have that.

Right. That would be cool though.

>>You can declare defunned functions as inline 
>>functions which you cannot do for generic functions, but I don't think 
>>even that would have convinced the CL designers to keep defun because 
>>they regularly used the rationale for other design decisions that clever 
>>compilers can do wonders. (Richard Gabriel says something about these 
>>things in a paper criticizing Common Lisp.)
> 
> Can you quote places in the spec where the `sufficiently smart
> compiler' argument is used (or needs to be used)?

No, but Richard Gabriel's paper "A Critique of Common Lisp" - 
http://www.dreamsongs.com/NewFiles/clcrit.pdf - mentions this: "Too many 
costs of the language were dismissed with the admonition that �any good 
compiler� can take care of them. No one has yet written � nor is likely 
to without tremendous effort � a compiler that does a fraction of the 
tricks expected of it. At present, the �hope� for all COMMON LISP 
implementors is that an outstanding portable COMMON LISP compiler will 
be written and widely used."

He continues to mention some examples. (I recall reading at least one 
other paper that makes similar statements about defmethod. If you insist 
I can try to dig it up.)


Pascal

-- 
Pascal Costanza               University of Bonn
···············@web.de        Institute of Computer Science III
http://www.pascalcostanza.de  R�merstr. 164, D-53117 Bonn (Germany)
From: Duane Rettig
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <4658tb3by.fsf@franz.com>
Pascal Costanza <········@web.de> writes:

> No, but Richard Gabriel's paper "A Critique of Common Lisp" -
> 
> http://www.dreamsongs.com/NewFiles/clcrit.pdf - mentions this: "Too
> many costs of the language were dismissed with the admonition that
> any good compiler can take care of them. No one has yet written 
> nor is likely to without tremendous effort  a compiler that does a
> fraction of the tricks expected of it. At present, the hope for all
> COMMON LISP implementors is that an outstanding portable COMMON LISP
> compiler will be written and widely used."

What an incredibly depressing paper!  I had almost forgotten about it,
and when I read it again just now, it made me feel bad for my favorite
language...

But let's put this paper into context.  First, check out the date it
was written: 1984:

 1. "Common Lisp" was defined in terms of the first edition of CLtL.
The standardized language (the effort to create which addressed many
of those issues Brooks and Gabriel cite) was not to exist until fully
ten years later.  Compiler-macros did not standardly exist, so
rewriting heavyweight calls to functions with keywords (one of their
complaints) was no portably possible.  Indeed, I agree that CLtL1 was
not necessarily a very portable language, especially performance-wise.

 2. Gabriel was obviously interested in speed, a fact that was
borne out a year later in his writing of "Performance and Evaluation
of Lisp Systems" (MIT Press, 1985).  His cry for speed resulted in
manyfold speedups of all Lisp systems, inclusing most Common Lisps.

 3. The paper emphasizes the skewing of the language toward microcoded
architectures over GP hardware.  However, that position had no
foreknowledge of the generational-gcs invented in the late '80s,
presumably as a direct result of this "challenge".  Of course, not
all of the architectural challenges of getting the most efficiency out
of a GP machine have yet been met, but it is a good deal better now
than it was at the time this paper was written.

 4. It was written before or during the invention of CLOS and the MOP,
which has obvious connotations for the current discussion.

I think on the whole, if one considers the state of Lisp implementations
at the time, and the number of high-quality implementations available
now, the only conclusion to be made is that the Common Lisp community
did indeed step up to the challenge.

Now in order not to get sickeningly sweet on things, and to salt my
treatise with realism, we must consider that one of the paper's cries
is for what they call "transportability".  Obviously, the standards
committee paid great attention to portability of source code when they
considered what would become the 1994 spec.  And in fact those programs
written in pure Common Lisp tend to be highly portable.  However,
portability is still an issue, where programs make use of powerful
concepts and systems not covered by the spec, and it probably always
will be an issue, as long as there are many implementations of Common
Lisp as there are.  We can be depressed about this, or we can accept
it as a challenge to work out such issues by any means possible or
practical.

> He continues to mention some examples. (I recall reading at least one
> other paper that makes similar statements about defmethod. If you
> insist I can try to dig it up.)

Please do; we definitely need to put that one into context, as well.

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Pascal Costanza
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <ccugpj$nhu$1@f1node01.rhrz.uni-bonn.de>
Duane Rettig wrote:

> I think on the whole, if one considers the state of Lisp implementations
> at the time, and the number of high-quality implementations available
> now, the only conclusion to be made is that the Common Lisp community
> did indeed step up to the challenge.

Yesyesyesyes, and thanks a lot for putting things into perspective!!!

> However,
> portability is still an issue, where programs make use of powerful
> concepts and systems not covered by the spec, and it probably always
> will be an issue, as long as there are many implementations of Common
> Lisp as there are.  We can be depressed about this, or we can accept
> it as a challenge to work out such issues by any means possible or
> practical.

Again, I totally agree (with the latter, to be specific).

>>He continues to mention some examples. (I recall reading at least one
>>other paper that makes similar statements about defmethod. If you
>>insist I can try to dig it up.)
> 
> Please do; we definitely need to put that one into context, as well.

OK, it is, of course, the "worse is better" paper
(http://www.dreamsongs.com/WIB.html ). The sections I had in mind are
the following (both in 3.6 "The Next Lisp"):

"Some aspects of the extreme dynamism of Common Lisp should be
reexamined, or at least the tradeoffs reconsidered. For example, how
often does a real program do this?

     (defun f ...)

     (dotimes (...)
       ...
       (setf (symbol-function 'f) #'(lambda ...))
       ...)

Implementations of the next Lisp should not be influenced by previous
implementations to make this operation fast, especially at the expense
of poor performance of all other function calls."

(BTW, doesn't this mean that even defun always needs a level of
indirection, unless declaimed inlineable?)

He then continues to describe a sketch of a layered approach to Lisp:

"In the fourth layer I include those capabilities that an environment
can and should provide, but which must be standardized. A typical
example is defmethod from CLOS. In CLOS, generic functions are made of
methods, each method applicable to certain classes. The first layer has
a definition form for a complete generic function -- that is, for a
generic function along with all of its methods, defined in one place
(which is how the layer 1 compiler wants to see it). There will also be
means of associating a name with the generic function. However, while
developing a system, classes will be defined in various places, and it
makes sense to be able to see relevant (applicable) methods adjacent to
these classes. defmethod is the construct to define methods, and
defmethod forms can be placed anywhere amongst other definitional forms.

But methods are relevant to each class on which the method is
specialized, and also to each subclass of those classes. So, where
should the unique defmethod form be placed? The environment should allow
the programmer to see the method definition in any or all of these
places, while the real definition should be in some particular place.
That place might as well be in the single generic function definition
form, and it is up to the environment to show the defmethod equivalent
near relevant classes when required, and to accept as input the source
in the form of a defmethod (which it then places in the generic function
definition)."

What I get from these two sections, in relation to the current thread,
is that adding or removing methods at runtime wouldn't be possible with
such an approach, right? This isn't explicitly stated, but the
expression "how the layer 1 compiler wants to see it" seems to indicate
that that compiler wants a closed ("sealed") definition of a generic
function. However, the ANSI standard doesn't preclude method definitions
at any time. (Even without a MOP, one can always say (eval `(defmethod
...)).)



Pascal

-- 
Pascal Costanza               University of Bonn
···············@web.de        Institute of Computer Science III
http://www.pascalcostanza.de  R�merstr. 164, D-53117 Bonn (Germany)
From: Duane Rettig
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <41xjhau6x.fsf@franz.com>
Pascal Costanza <········@web.de> writes:

> Duane Rettig wrote:
> 
> > I think on the whole, if one considers the state of Lisp implementations
> > at the time, and the number of high-quality implementations available
> > now, the only conclusion to be made is that the Common Lisp community
> > did indeed step up to the challenge.
> 
> Yesyesyesyes, and thanks a lot for putting things into perspective!!!

No problem.

> > However,
> > portability is still an issue, where programs make use of powerful
> > concepts and systems not covered by the spec, and it probably always
> > will be an issue, as long as there are many implementations of Common
> > Lisp as there are.  We can be depressed about this, or we can accept
> > it as a challenge to work out such issues by any means possible or
> > practical.
> 
> Again, I totally agree (with the latter, to be specific).

Good.  On to "worse is better":

> >>He continues to mention some examples. (I recall reading at least one
> >>other paper that makes similar statements about defmethod. If you
> >>insist I can try to dig it up.)
> > Please do; we definitely need to put that one into context, as well.
> 
> 
> OK, it is, of course, the "worse is better" paper
> (http://www.dreamsongs.com/WIB.html ).

I've always had a love/hate relationship with this paper and its
philosophy.  Note that Gabriel himself calls his philosophy a
"caricature", and he does this intentionally to bring out what
he considers to be important distinctions between the "right"
approach and the "worse" approach.  He even starts it off correctly
by providing sets of criteria by which to judge designs: correctness,
completeness, consistency, simplicity.  However, he does not consider
the effects of other design criteria such as speed, nor other external
design factors such as budget or schedule.  Design criteria constantly
shift, and one must consider all factors.  For example, if one has a
choice of getting something done in 1 year that almost works, as opposed
to waiting N years until it is done right, then after N-1 years the first
approach will have had N-2 years of field experience, and might even have
had a possibility of being redesigned to take on the right approach,
whereas the second approach will at the end of N-1 years produce nothing
yet, and no field experience has been gained.  In a competitive situation,
that could be fatal to the company considering the "right" approach, and
so that company will go out of business and the "right" approach is never
completed.  The moral is that all correct designs are done based on a set
of design criteria, and when somebody says something like "let's bite the
bullet and to the right thing" what they're more likely saying is that
they don't like the priorities of the design criteria, and thus want
to raise one criterion higher than it was.

The paper notes the differences between the "right" approach and the
"worse" approach, but doesn't put it into context of the many, many
approaches that are possible.  Instead, his caricature looks like
a rivalry between "MIT and New Jersey" (with "New Jersy" being an
unveiled reference to the Unix style).  His feud with Unix seems bitter,
but since I'm neither from MIT nor from New Jersey, although I get the
joke, it ceases to be funny after so many years.  And although the
caricature does draw attention toward the problem by those outside,
it tends then to draw the focus of those on the inside to the
caricature itself, rather than to the real problem.

> The sections I had in mind are
> the following (both in 3.6 "The Next Lisp"):
> 
> "Some aspects of the extreme dynamism of Common Lisp should be
> reexamined, or at least the tradeoffs reconsidered. For example, how
> often does a real program do this?
> 
>      (defun f ...)
> 
>      (dotimes (...)
>        ...
>        (setf (symbol-function 'f) #'(lambda ...))
>        ...)

The Correctness criterion begs a differnt question: "Can this ever
happen?" to which the answer is, of course, "Yes".  The question
he actually asks, however, is a question basesd on a Performance
criterion, which he never listed as one of the major criteria in
his paper.

> Implementations of the next Lisp should not be influenced by previous
> implementations to make this operation fast, especially at the expense
> of poor performance of all other function calls."

He gives no measurements to indicate what he thinks is the poor
performance of a function call, nor does he compare it to "worse"
implementations.

> (BTW, doesn't this mean that even defun always needs a level of
> indirection, unless declaimed inlineable?)

A function defined and called within a file and compiled with compile-file
might remove that indirection.  But again, where are the numbers that
show such indirection to be bad for performance?

> He then continues to describe a sketch of a layered approach to Lisp:
> 
  [ Perfect argument for advocating sealing elided ... ]

> What I get from these two sections, in relation to the current thread,
> is that adding or removing methods at runtime wouldn't be possible with
> such an approach, right? This isn't explicitly stated, but the
> expression "how the layer 1 compiler wants to see it" seems to indicate
> that that compiler wants a closed ("sealed") definition of a generic
> function. However, the ANSI standard doesn't preclude method definitions
> at any time. (Even without a MOP, one can always say (eval `(defmethod
> ...)).)

Correct.  Now, what approach might you take to such an issue?

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Pascal Costanza
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <cd0hi4$14h2$1@f1node01.rhrz.uni-bonn.de>
Duane Rettig wrote:

>>Implementations of the next Lisp should not be influenced by previous
>>implementations to make this operation fast, especially at the expense
>>of poor performance of all other function calls."
> 
> He gives no measurements to indicate what he thinks is the poor
> performance of a function call, nor does he compare it to "worse"
> implementations.

OK, good point.

>>(BTW, doesn't this mean that even defun always needs a level of
>>indirection, unless declaimed inlineable?)
> 
> A function defined and called within a file and compiled with compile-file
> might remove that indirection.  But again, where are the numbers that
> show such indirection to be bad for performance?

Yep, I should have thought of that. As Christophe Rhodes said in his 
talk at the Lisp workshops, the outcome of benchmarks can be highly 
counterintuitive. I myself have had the experience with a benchmark in 
which a solution using double indirection was in fact more efficient 
than the one without.

>>He then continues to describe a sketch of a layered approach to Lisp:
> 
>   [ Perfect argument for advocating sealing elided ... ]
> 
>>What I get from these two sections, in relation to the current thread,
>>is that adding or removing methods at runtime wouldn't be possible with
>>such an approach, right? This isn't explicitly stated, but the
>>expression "how the layer 1 compiler wants to see it" seems to indicate
>>that that compiler wants a closed ("sealed") definition of a generic
>>function. However, the ANSI standard doesn't preclude method definitions
>>at any time. (Even without a MOP, one can always say (eval `(defmethod
>>...)).)
> 
> Correct.  Now, what approach might you take to such an issue?

Well, I think sealing is a good idea. Maybe it's a good idea to have two 
kinds of seals, breakable and unbreakable ones. (eval `(defmethod ...)) 
then might raise a continuable error when the respective generic 
function has a breakable seal, or a non-continuable error when it has an 
unbreakable seal.

 From that point of view, defun just creates functions with unbreakable 
seals.

Hmm, I am not sure if that's what you wanted to ask...


Pascal

-- 
Pascal Costanza               University of Bonn
···············@web.de        Institute of Computer Science III
http://www.pascalcostanza.de  R�merstr. 164, D-53117 Bonn (Germany)
From: Gareth McCaughan
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <87vfgt7xpo.fsf@g.mccaughan.ntlworld.com>
Pascal Costanza wrote:

> OK, it is, of course, the "worse is better" paper
> (http://www.dreamsongs.com/WIB.html ). The sections I had in mind are
> the following (both in 3.6 "The Next Lisp"):
> 
> "Some aspects of the extreme dynamism of Common Lisp should be
> reexamined, or at least the tradeoffs reconsidered. For example, how
> often does a real program do this?
> 
>      (defun f ...)
> 
>      (dotimes (...)
>        ...
>        (setf (symbol-function 'f) #'(lambda ...))
>        ...)
> 
> Implementations of the next Lisp should not be influenced by previous
> implementations to make this operation fast, especially at the expense
> of poor performance of all other function calls."
> 
> (BTW, doesn't this mean that even defun always needs a level of
> indirection, unless declaimed inlineable?)

No. The implementation could remember the locations of all
calls to each function, and patch them if the function gets
redefined.

-- 
Gareth McCaughan
.sig under construc
From: Pascal Costanza
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <cd0hne$1362$1@f1node01.rhrz.uni-bonn.de>
Gareth McCaughan wrote:

> Pascal Costanza wrote:
> 
>>(BTW, doesn't this mean that even defun always needs a level of
>>indirection, unless declaimed inlineable?)
> 
> No. The implementation could remember the locations of all
> calls to each function, and patch them if the function gets
> redefined.

I think that's a pretty complex optimization to add to a runtime system. 
IBM and Sun have managed to do that for Java, but it took them a lot of 
work AFAICT.


Pascal

-- 
Pascal Costanza               University of Bonn
···············@web.de        Institute of Computer Science III
http://www.pascalcostanza.de  R�merstr. 164, D-53117 Bonn (Germany)
From: Frode Vatvedt Fjeld
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <2hfz7w6pbm.fsf@vserver.cs.uit.no>
Gareth McCaughan <················@pobox.com> writes:

> No. The implementation could remember the locations of all calls to
> each function, and patch them if the function gets redefined.

Is there any implementation that actually does this? If not, what are
the decisive reasons for this? (Not a rhetorical question.)

-- 
Frode Vatvedt Fjeld
From: Pascal Costanza
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <cd0n4b$mbs$1@f1node01.rhrz.uni-bonn.de>
Frode Vatvedt Fjeld wrote:

> Gareth McCaughan <················@pobox.com> writes:
> 
>>No. The implementation could remember the locations of all calls to
>>each function, and patch them if the function gets redefined.
> 
> Is there any implementation that actually does this? If not, what are
> the decisive reasons for this? (Not a rhetorical question.)

I am no expert on this topic, but from what I have heard the devil lies 
in the details. For example, if you re-inline a redefined function, the 
code size of the call site changes, jump targets need to be 
recalculated, and so on. Effectively, you need to recompile the call 
site. Now imagine that that call site is currently executed, so you also 
have to recalculate the program counter. This can happen for both other 
threads and the current thread in the general case. Furthermore, if you 
recompile the call site, and that function was again inlined somewhere 
else, you have to do all of these things in turn for its call sites, and 
so on.

Since this can become very costly, you have to measure at runtime 
whether the cost/benefit ratio is good enough for inlining a function, 
so you need to count function calls and apply appriate heuristics. These 
things depend heavily on the actual CPU, the operating system used, etc. 
I'll stop here. ;)


Pascal

-- 
Pascal Costanza               University of Bonn
···············@web.de        Institute of Computer Science III
http://www.pascalcostanza.de  R�merstr. 164, D-53117 Bonn (Germany)
From: Duane Rettig
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <4d62zoou8.fsf@franz.com>
Pascal Costanza <········@web.de> writes:

> Frode Vatvedt Fjeld wrote:
> 
> > Gareth McCaughan <················@pobox.com> writes:
> >
> 
> >>No. The implementation could remember the locations of all calls to
> >>each function, and patch them if the function gets redefined.
> > Is there any implementation that actually does this? If not, what are
> > the decisive reasons for this? (Not a rhetorical question.)

See

http://groups.google.com/groups?selm=4brj1ozfu.fsf%40franz.com&output=gplain

for a descriptio of our experience.

> I am no expert on this topic, but from what I have heard the devil
> lies in the details. For example, if you re-inline a redefined
> function, the code size of the call site changes, jump targets need to
> be recalculated, and so on. Effectively, you need to recompile the
> call site. Now imagine that that call site is currently executed, so
> you also have to recalculate the program counter. This can happen for
> both other threads and the current thread in the general

These weren't a problem in our situation.  The reccoding was done
lazily by the calling mechanism itself, so it only occurred at a
time when the triggering calling sequence had gotten to the call
instruction itself.  As for code sizes changing, I took care that the
old and new calling sequences were precisely the same size, actually
pretty easy to do on a RISC architecture.

> case. Furthermore, if you recompile the call site, and that function
> was again inlined somewhere else, you have to do all of these things
> in turn for its call sites, and so on.

In our case, we had the lazy blasting of the code vector do it in place
atomically, so that no actual addresses needed to move.  A programmer
with fine programming sensibilities might be horrified and say "Self
modifying code! Argh!", but in fact we were not doing anything more
than slightly finer grained trap handling on a per-call basis than
operating systems do on a per-page basis.  And since the cache-flushing
instructions available to us were on a per-line basis, the granularity
almost matched anyway.

> Since this can become very costly, you have to measure at runtime
> whether the cost/benefit ratio is good enough for inlining a function,
> so you need to count function calls and apply appriate
> heuristics. These things depend heavily on the actual CPU, the
> operating system used, etc. I'll stop here. ;)

You're absolutely correct, but perhaps the cost was in a different place
than expected.  As always, the mantra is "measure, measure, measure".
We had even done the measurements, and were satisfied, if not pleased,
with the slight increase in speed that might give us an edge, but then
a hidden cost showed itself in that code vectors could not be shared,
because they now had the potential to contain absolute addresses in
them, and so some of our customers' larger apps blew up in size on the
rs/6000, and became unacceptably large.  So we deemed the cost too
great, but for reasons we had never anticipated (those other costs,
such as complexity, amortized fixup costs, etc, we had anticipated
and deemed acceptable those costs).

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Kalle Olavi Niemitalo
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <87acy6cvqd.fsf@Astalo.kon.iki.fi>
Pascal Bourguignon <····@thalassa.informatimago.com> writes:

> (defun f-area (stuff)
>   (typecase stuff
>     (shape 0)
>     (square (sq (side square)))))

TYPECASE chooses the earliest applicable clause, so you should
check for SQUARE before SHAPE, if the result is to match that
achieved with DEFMETHOD.
From: Pascal Bourguignon
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <87r7rhbq9j.fsf@thalassa.informatimago.com>
Kalle Olavi Niemitalo <···@iki.fi> writes:

> Pascal Bourguignon <····@thalassa.informatimago.com> writes:
> 
> > (defun f-area (stuff)
> >   (typecase stuff
> >     (shape 0)
> >     (square (sq (side square)))))
> 
> TYPECASE chooses the earliest applicable clause, so you should
> check for SQUARE before SHAPE, if the result is to match that
> achieved with DEFMETHOD.

Yes, one more reason why to choose defmethod when you want methods :-)
(But the question was not defmethod but defun, sorry).

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

There is no worse tyranny than to force a man to pay for what he does not
want merely because you think it would be good for him. -- Robert Heinlein
From: Kenny Tilton
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <YOeIc.17523$oW6.4230098@twister.nyc.rr.com>
Jeff wrote:
> appears to be a macro that does everything that defun can and more. So
> why shouldn't I just use defmethod /everywhere/ instead of defun?

efficiency

kt


-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
From: Kalle Olavi Niemitalo
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <87d632cvy2.fsf@Astalo.kon.iki.fi>
"Jeff" <···@mfire.com> writes:

> So why shouldn't I just use defmethod /everywhere/ instead of defun?

If you use defun, people reading the definition can assume that
any calls to a function with that name will indeed execute the
code in the definition.  With defmethod, one cannot be sure
there aren't more methods defined elsewhere.

Calls to a method of a generic function are likely to be slower
than calls to a plain function, because Lisp has to check
whether the method is applicable to the parameters.

If you put a generic function in the public interface of a
library, you should document whether the user of the library may
define more methods and what requirements such methods must
fulfill.
From: Wade Humeniuk
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <inDIc.26859$Rf.12415@edtnps84>
Jeff wrote:

> Aside from being able to declare an argument that is a class, how are
> these different from any other defun? Why even have defmethod? It just
> appears to be a macro that does everything that defun can and more. So
> why shouldn't I just use defmethod /everywhere/ instead of defun?

Reason #1

DEFUN is not DEFMETHOD.  The OO paradigm is _a_ way of organizing your
code, but, it is not the only way.  DEFMETHOD is a later addition to
Lisp, though Lisp is inherently OO.  Having only one way to do something
(or disallowing new ways) in a language, I have come to believe, is inherently
fatal.  Lisp allows diversity.

Reason #2

In the details of an application's implementation it is probably easier
to implement dynamic changes to the runtime by utilizing DEFUN more than
DEFMETHOD.  It can be a little tricky to, say, remove a :before method
on some class (it is no longer needed) and to be sure you have not
introduced some error in your app.  A generic function (defmethod) can
be dispersed over many actual methods and the locality of expression
can be lost.  Add to this an MOP where one can not be really sure how the
method dispatching actual works.  It can take more discipline to keep the
implementation from octopussing out of control.  DEFUN has one and only one
entry point and one is sure that when one changes a function definition
that one has singularized the flow the logic.

Wade
From: Thomas Schilling
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <opsa3k96w4trs3c0@news.CIS.DFN.DE>
Wade Humeniuk wrote:

> In the details of an application's implementation it is probably easier
> to implement dynamic changes to the runtime by utilizing DEFUN more than
> DEFMETHOD.  It can be a little tricky to, say, remove a :before method
> on some class (it is no longer needed) and to be sure you have not
> introduced some error in your app.  A generic function (defmethod) can
> be dispersed over many actual methods and the locality of expression
> can be lost.

As stated so often. A nice IDE really helps. I'm currently trying 
(part-time) to add a method-browser to SLIM. It'll be ready Real Soon Now. 
(Well, will, be my first Emacs mode ...).

Ok, planned features:
  - list all methods of a gf
  - allow jumping to them
  - allow removing them
  - possibly mark methods with no accessible code (since I quite often 
happen to redefine a method with a new class specialized on, which 
unfortunately doesn't remove the old method.)
  - show them in execution order (should possible be possible via the 
method combination)

There's currently a useful workaround in SLIME via the REPL + inspector:
  * #'mygf
  C-c I *
  ... find the method ...
  M-Ret (copy selected method to inspector)
  * (remove-method ** *)

>  Add to this an MOP where one can not be really sure how the
> method dispatching actual works.  It can take more discipline to keep the
> implementation from octopussing out of control.

Okay, this is a little more complicated to handle via an IDE.
-- 
      ,,
     \../   /  <<< The LISP Effect
    |_\\ _==__
__ | |bb|   | _________________________________________________
From: Matthew Danish
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <Pine.LNX.4.58-035.0407131908240.16923@unix45.andrew.cmu.edu>
On Wed, 14 Jul 2004, Thomas Schilling wrote:
> Ok, planned features:
>   - list all methods of a gf
>   - allow jumping to them
>   - allow removing them
>   - possibly mark methods with no accessible code (since I quite often
> happen to redefine a method with a new class specialized on, which
> unfortunately doesn't remove the old method.)
>   - show them in execution order (should possible be possible via the
> method combination)

Could you add this to the already-existing XREF support for methods?
Look at the slime-xref-mode part of slime.el, I bet it wouldn't be too
difficult to add a function to send remove-method to the lisp, and other
things.
From: Asle Olufsen
Subject: Re: Purpose of defmethod
Date: 
Message-ID: <vpsmbwjpf3.fsf@skoyern.nextra.no>
"Jeff" <···@mfire.com> writes:

> So why shouldn't I just use defmethod /everywhere/ instead of defun?

There's as style guide that says: 

Use the most specific construct that does the job.

So by using defun, if you do not "need" defmethod, it's easer to convey
the intention of the code to the reader.

Oluf