Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Unusual method combinations

69 views
Skip to first unread message

Spiros Bousbouras

unread,
Jun 1, 2022, 3:19:51 PM6/1/22
to
Sometimes when I read the various CLOS facilities I wonder whether the
standards committee got a bit too "trigger happy" in adding features
and whether anyone has a use for them. So I was wondering :

1. Has anyone used method combinations other than the standard one ?
In particular any of those in "7.6.6.4 Built-in Method Combination Types" ?

2. Have you ever defined your own method combinations using
DEFINE-METHOD-COMBINATION ? If yes , did they take a lambda list ?
I mean the part in the syntax define-method-combination name lambda-list .

Do you happen to know whether any Lisp dialects leading up to Common Lisp had
object systems providing facilities similar to the above ?

--
"But in Special Circumstances we deal in the moral equivalent of black holes,
where the normal laws - the rules of right and wrong that people imagine
apply everywhere else in the universe - break down; beyond those metaphysical
event-horizons, there exist... special circumstances." She smiled. "That's
us. That's our territory; our domain."
"Use of weapons" by Iain Banks

Lieven Marchand

unread,
Jun 1, 2022, 3:36:42 PM6/1/22
to
Spiros Bousbouras <spi...@gmail.com> writes:

> Sometimes when I read the various CLOS facilities I wonder whether the
> standards committee got a bit too "trigger happy" in adding features
> and whether anyone has a use for them. So I was wondering :
>
> 1. Has anyone used method combinations other than the standard one ?
> In particular any of those in "7.6.6.4 Built-in Method Combination Types" ?
>
> 2. Have you ever defined your own method combinations using
> DEFINE-METHOD-COMBINATION ? If yes , did they take a lambda list ?
> I mean the part in the syntax define-method-combination name lambda-list .
>
> Do you happen to know whether any Lisp dialects leading up to Common Lisp had
> object systems providing facilities similar to the above ?

There is an implementation of the Eiffel language design by contract as
a custom method combination. I don't think it's ever been used in anger
for a large system but it shows the flexibility.

IIRC there are also custom method combinations in CLIM.

--
Laat hulle almal sterf. Ek is tevrede om die wêreld te sien brand en die vallende
konings te spot. Ek en my aasdier sal loop op die as van die verwoeste aarde.

Zyni Moë

unread,
Jun 1, 2022, 5:30:10 PM6/1/22
to
Spiros Bousbouras <spi...@gmail.com> wrote:
>
> 1. Has anyone used method combinations other than the standard one ?
> In particular any of those in "7.6.6.4 Built-in Method Combination Types" ?

Yes. progn, and, or for instance are very useful, probably have also used
append and/or list.

>
> 2. Have you ever defined your own method combinations using
> DEFINE-METHOD-COMBINATION ? If yes , did they take a lambda list ?
> I mean the part in the syntax define-method-combination name lambda-list .

Yes and yes. Well, I am profligate consumer of the wrapping-standard
method combination which does (think I originally defined my own before I
had found that one).


--
the small snake

Zyni Moë

unread,
Jun 1, 2022, 5:32:36 PM6/1/22
to
Zyni Moë <no_e...@invalid.invalid> wrote:
> I am profligate consumer of the wrapping-standard
> method combination which does (think I originally defined my own before I
> had found that one).

Is worth pointing out that is easy to experimentally check that method
combinations such as above have no run-time overhead.



--
the small snake

Spiros Bousbouras

unread,
Jun 1, 2022, 7:49:07 PM6/1/22
to
On Wed, 1 Jun 2022 21:30:05 -0000 (UTC) Zyni Moë wrote:
> Spiros Bousbouras <spi...@gmail.com> wrote:
> >
> > 1. Has anyone used method combinations other than the standard one ?
> > In particular any of those in "7.6.6.4 Built-in Method Combination Types" ?
>
> Yes. progn, and, or for instance are very useful, probably have also used
> append and/or list.

Can you say more like what you were writing ? Because personally I can't think
of an occasion where I would find the operator method combinations useful but
I wouldn't be able to achieve the same functionality in some other way , likely
a more straightforward one.

> > 2. Have you ever defined your own method combinations using
> > DEFINE-METHOD-COMBINATION ? If yes , did they take a lambda list ?
> > I mean the part in the syntax define-method-combination name lambda-list .
>
> Yes and yes. Well, I am profligate consumer of the wrapping-standard
> method combination which does (think I originally defined my own before I
> had found that one).

Do you mean :around methods ? These only take :most-specific-first or
:most-specific-last arguments. You actually had a use for those ?

Replying to <t78ltg$4nq$1...@dont-email.me> :

> > I am profligate consumer of the wrapping-standard
> > method combination which does (think I originally defined my own before I
> > had found that one).
>
> Is worth pointing out that is easy to experimentally check that method
> combinations such as above have no run-time overhead.

I would imagine that depends on the implementation.

Didier Verna

unread,
Jun 2, 2022, 4:50:39 AM6/2/22
to
Spiros Bousbouras <spi...@gmail.com> rote:

> Can you say more like what you were writing ? Because personally I
> can't think of an occasion where I would find the operator method
> combinations useful but I wouldn't be able to achieve the same
> functionality in some other way , likely a more straightforward one.

Caution here: define straightforward. If you're uncomfortable with
method combinations, you may find something else more straightforward,
just because you're not used to method combinations enough.

Disregarding subjectivity (personal experience, style preference,
etc.) as much as possible, I would say this: method combinations allow
you to express a different dispatch algorithm in a declarative way,
rather than in an imperative one. Consequently, there is something I
grew more and more vigilant about over the years: every time I start
using CALL-NEXT-METHOD and friends (which /may/ appear more
straightforward in some sense), I ask myself whether or not I wouldn't
be starting to implement a different combination without actually
realizing it, and most of the time, I am. Now, whether or not it's
worth the trouble to go declarative is also a matter of taste, to some
extent, but IMO, mixing dispatch code and actual methods code together
is never a good think for SoC, and software engineering in general.

Apart from that, yes, for simple cases you may want to avoid the
method combination artillery altogether, but hell, you may also want
to avoid generic functions and use a couple of TYPECASE calls
instead...

> Do you mean :around methods ? These only take :most-specific-first or
> :most-specific-last arguments. You actually had a use for those ?

I have an example in Clon (clon/core/src/output/sheet.lisp). In
general, yes, I find the operator-based standard method combinations
quite usefull (although preferably extended with :before / :after / and
:around).

More recently, I developed a pretty elaborate (but it's only 10 lines
long, so in fact it's pretty straightforward ;-)) method combination
for Declt 4, in the documentation rendering code. I don't have the
time to explain it here right now, but you can find it in
declt/core/src/doc/cod.lisp currently. Trust me on this, thanks to
that, the documentation code became so much cleaner than in version
3...

--
Resistance is futile. You will be jazzimilated.

Lisp, Jazz, Aïkido: http://www.didierverna.info

Zyni Moë

unread,
Jun 2, 2022, 6:01:20 AM6/2/22
to
Spiros Bousbouras <spi...@gmail.com> wrote:

> Can you say more like what you were writing ? Because personally I can't think
> of an occasion where I would find the operator method combinations useful but
> I wouldn't be able to achieve the same functionality in some other way , likely
> a more straightforward one.
>

For instance logging: want all methods on the log object to run, use progn
and they will now all run. Or checking some object allows some action:
want all methods on it to return true, use and, this will then happen.

>
> Do you mean :around methods ? These only take :most-specific-first or
> :most-specific-last arguments. You actually had a use for those ?

No I mean wrapping methods, which run outside around methods and in most
specific last order. wrapping method means that class near top of
inheritance graph can establish dynamic state around all other methods and
know that it will not be overridden, or can establish default values for
arguments:

(defvar *blob-cache-default* t)

(defgeneric blob (x &key cache)
(:method-combination wrapping-standard)
(:method :wrapping (x &key (cache *blob-cache-default*))
(call-next-method x :cache cache)))

now no other methods need to worry about the default for the cache
argument: it is defined in one place, not many.

>>
>> Is worth pointing out that is easy to experimentally check that method
>> combinations such as above have no run-time overhead.
>
> I would imagine that depends on the implementation.
>

Any PCL-derived implementation I think, unless they have gone out of their
way to break things. Perhaps there are non-PCL-derived implementations.

As other person says, if you find method combinations unuseful is perhaps
because you have spent too much time with the many primitive languages
where you have to manually construct them by establishing explicit protocol
for methods 'this method should do its check and if it succeeds it must
invoke the next method and return its result otherwise return false' is the
sort of awful manual errorful pain you must do in Python say to implement
and method combination.

--
the small snake

Spiros Bousbouras

unread,
Jun 3, 2022, 2:53:04 PM6/3/22
to
On Wed, 01 Jun 2022 21:36:30 +0200
Lieven Marchand <m...@wyrd.be> wrote:
> Spiros Bousbouras <spi...@gmail.com> writes:
>
> > Sometimes when I read the various CLOS facilities I wonder whether the
> > standards committee got a bit too "trigger happy" in adding features
> > and whether anyone has a use for them. So I was wondering :
> >
> > 1. Has anyone used method combinations other than the standard one ?
> > In particular any of those in "7.6.6.4 Built-in Method Combination Types" ?
> >
> > 2. Have you ever defined your own method combinations using
> > DEFINE-METHOD-COMBINATION ? If yes , did they take a lambda list ?
> > I mean the part in the syntax define-method-combination name lambda-list .
> >
> > Do you happen to know whether any Lisp dialects leading up to Common Lisp had
> > object systems providing facilities similar to the above ?
>
> There is an implementation of the Eiffel language design by contract as
> a custom method combination. I don't think it's ever been used in anger
> for a large system but it shows the flexibility.

There is where ?

Spiros Bousbouras

unread,
Jun 3, 2022, 3:03:51 PM6/3/22
to
On Thu, 02 Jun 2022 10:50:33 +0200
Didier Verna <did...@lrde.epita.fr> wrote:
> Spiros Bousbouras <spi...@gmail.com> rote:
>
> > Can you say more like what you were writing ? Because personally I
> > can't think of an occasion where I would find the operator method
> > combinations useful but I wouldn't be able to achieve the same
> > functionality in some other way , likely a more straightforward one.
>
> Caution here: define straightforward. If you're uncomfortable with
> method combinations, you may find something else more straightforward,
> just because you're not used to method combinations enough.

I don't have a definition and I don't want to disregard subjective factors.
My question applies regardless of whether people made their choices using
objective or subjective factors. [ Not that it's possible to completely
omit subjective factors , even the choice of programming language is often
subjective. ]

> Disregarding subjectivity (personal experience, style preference,
> etc.) as much as possible, I would say this: method combinations allow
> you to express a different dispatch algorithm in a declarative way,
> rather than in an imperative one. Consequently, there is something I
> grew more and more vigilant about over the years: every time I start
> using CALL-NEXT-METHOD and friends (which /may/ appear more
> straightforward in some sense), I ask myself whether or not I wouldn't
> be starting to implement a different combination without actually
> realizing it, and most of the time, I am. Now, whether or not it's
> worth the trouble to go declarative is also a matter of taste, to some
> extent, but IMO, mixing dispatch code and actual methods code together
> is never a good think for SoC, and software engineering in general.

SoC ?

> Apart from that, yes, for simple cases you may want to avoid the
> method combination artillery altogether, but hell, you may also want
> to avoid generic functions and use a couple of TYPECASE calls
> instead...
>
> > Do you mean :around methods ? These only take :most-specific-first or
> > :most-specific-last arguments. You actually had a use for those ?
>
> I have an example in Clon (clon/core/src/output/sheet.lisp). In
> general, yes, I find the operator-based standard method combinations
> quite usefull (although preferably extended with :before / :after / and
> :around).

Operator method combinations only support :around methods.

> More recently, I developed a pretty elaborate (but it's only 10 lines
> long, so in fact it's pretty straightforward ;-)) method combination
> for Declt 4, in the documentation rendering code. I don't have the
> time to explain it here right now, but you can find it in
> declt/core/src/doc/cod.lisp currently. Trust me on this, thanks to
> that, the documentation code became so much cleaner than in version
> 3...

Where do I find this code ? It doesn't seem to exist under
www.didierverna.info .

--
'General Systems Vehicle internal explosion protection,' the drone explained,
letting the humans board the capsule first. 'Snaps anything significantly more
powerful than a fart straight into hyperspace; blast, radiation; the lot.'

Zyni Moë

unread,
Jun 3, 2022, 3:24:35 PM6/3/22
to
Spiros Bousbouras <spi...@gmail.com> wrote:

>
> Do you happen to know whether any Lisp dialects leading up to Common Lisp had
> object systems providing facilities similar to the above ?
>

Both CommonLoops (Xerox) and New Flavors (Symbolics) allowed user-defined
method combinations. CommonLoops probably borrowed the idea from New
Flavors:

> CommonLoops is practically a superset of New Flavors.CommonLoops
> andFlavors share the notion of generic function. In developing
> CommonLoops we have included the Flavors mechanism for user-defined method combination.

From https://interlisp.org/docs/1986-commonloops.pdf

--
the small snake

Lieven Marchand

unread,
Jun 3, 2022, 3:29:42 PM6/3/22
to

Spiros Bousbouras

unread,
Jun 3, 2022, 3:49:23 PM6/3/22
to
On Thu, 2 Jun 2022 10:01:15 -0000 (UTC) Zyni Moë wrote:
> Spiros Bousbouras <spi...@gmail.com> wrote:
>
> > Can you say more like what you were writing ? Because personally I can't think
> > of an occasion where I would find the operator method combinations useful but
> > I wouldn't be able to achieve the same functionality in some other way , likely
> > a more straightforward one.
> >
>
> For instance logging: want all methods on the log object to run, use progn
> and they will now all run. Or checking some object allows some action:
> want all methods on it to return true, use and, this will then happen.
>
> > Do you mean :around methods ? These only take :most-specific-first or
> > :most-specific-last arguments. You actually had a use for those ?
>
> No I mean wrapping methods, which run outside around methods and in most
> specific last order. wrapping method means that class near top of
> inheritance graph can establish dynamic state around all other methods and
> know that it will not be overridden, or can establish default values for
> arguments:
>
> (defvar *blob-cache-default* t)
>
> (defgeneric blob (x &key cache)
> (:method-combination wrapping-standard)
> (:method :wrapping (x &key (cache *blob-cache-default*))
> (call-next-method x :cache cache)))
>
> now no other methods need to worry about the default for the cache
> argument: it is defined in one place, not many.

Where does this wrapping-standard method combination come from ? It's not
part of the CL standard.

> >> Is worth pointing out that is easy to experimentally check that method
> >> combinations such as above have no run-time overhead.
> >
> > I would imagine that depends on the implementation.
> >
>
> Any PCL-derived implementation I think, unless they have gone out of their
> way to break things. Perhaps there are non-PCL-derived implementations.
>
> As other person says, if you find method combinations unuseful is perhaps
> because you have spent too much time with the many primitive languages
> where you have to manually construct them by establishing explicit protocol
> for methods 'this method should do its check and if it succeeds it must
> invoke the next method and return its result otherwise return false' is the
> sort of awful manual errorful pain you must do in Python say to implement
> and method combination.

No , I wasn't thinking in terms of Python at all. But for example one
annoyance for me in CL is that methods cannot be called with FUNCALL [7.6.2
Introduction to Methods] although conceptually they are like functions. If
you could call them using FUNCALL , you could implement operator method
combinations as follows :

PROGN :
(dolist (method (compute-applicable-methods generic-function ...args...))
(funcall method ...args...))

It would be more or less equally easy with any other operator you want.
Instead the standard provides an entirely different interface instead of
reusing other parts of the language. It would be even more convenient if
COMPUTE-APPLICABLE-METHODS returned a vector of methods instead of a list and
, while a method M is executing , you would have a way to get the vector V M
is part of and the position i of M in V [for this particular invocation of
the generic function M is part of] .This way , you wouldn't need
NEXT-METHOD-P but instead examine if i is the greatest position in V .Also
, you wouldn't need CALL-NEXT-METHOD but , instead could simply do

(funcall (aref V (1+ i)) ...args...) .I would also find it more aesthetic if
ADD-METHOD also accepted as a 2nd argument [i.e. the method argument] forms
like (function symbol) or (lambda (...) ...code...) .

Perhaps there are good reasons why the standard forces methods to be treated
very differently from functions but I can't think of such reasons.

One could implement some of the above ideas as an alternative way of doing
generic functions and methods and this is the kind of thing I'm thinking
might be more straightforward to use.

--
The American Mathematical Society's 1979 subject classification contains 61
basic classifications having approximately 3400 subcategories, and it has
been estimated that the number of new theorems published yearly in
mathematics journals is in excess of 100,000.
http://web.mst.edu/~lmhall/0-Introduction.pdf

Zyni Moë

unread,
Jun 3, 2022, 5:52:20 PM6/3/22
to
Spiros Bousbouras <spi...@gmail.com> wrote:
>
> Where does this wrapping-standard method combination come from ? It's not
> part of the CL standard.

Indeed it is not. it makes use of a facility which the standard has to
define your own, you see.

Do not think I will waste more time with this.

--
the small snake

Didier Verna

unread,
Jun 4, 2022, 5:32:11 AM6/4/22
to
Spiros Bousbouras <spi...@gmail.com> wrote:

> SoC ?

Separation of Concerns (orthogonality if you prefer). The idea being
that method combinations allow you to remove whatever dispatch-related
code there was in your methods before. Hence, what you put in your
methods is strictly focused on the job of the method itself, and
nothing else. The benefits in term of software engineering are
obvious: if you ever need to add or remove methods, you don't have to
modify the other ones to figure out who calls who, if you need to
change the ordering, there's a unique and central place to update (the
combination), etc., etc.

>> I have an example in Clon (clon/core/src/output/sheet.lisp). In
>> general, yes, I find the operator-based standard method
>> combinations quite usefull (although preferably extended with
>> :before / :after / and :around).
>
> Operator method combinations only support :around methods.

Which is why I said "preferably extended". See for example
https://www.lrde.epita.fr/~didier/research/publications/papers/verna.18.els.pdf


>> More recently, I developed a pretty elaborate (but it's only 10 lines
>> long, so in fact it's pretty straightforward ;-)) method combination
>> for Declt 4, in the documentation rendering code. I don't have the
>> time to explain it here right now, but you can find it in
>> declt/core/src/doc/cod.lisp currently. Trust me on this, thanks to
>> that, the documentation code became so much cleaner than in version
>> 3...
>
> Where do I find this code ? It doesn't seem to exist under
> www.didierverna.info .

https://github.com/didierverna/declt
https://github.com/didierverna/clon/

Stefan Monnier

unread,
Jun 4, 2022, 1:47:39 PM6/4/22
to
> Separation of Concerns (orthogonality if you prefer). The idea being
> that method combinations allow you to remove whatever dispatch-related
> code there was in your methods before. Hence, what you put in your
> methods is strictly focused on the job of the method itself, and
> nothing else. The benefits in term of software engineering are
> obvious: if you ever need to add or remove methods, you don't have to
> modify the other ones to figure out who calls who, if you need to
> change the ordering, there's a unique and central place to update (the
> combination), etc., etc.

I have trouble imagining cases where the methods wouldn't need to be
changed when the method combination is changed (but that's probably my
lack of exposure to uses of method combinations). IOW I have the
impression that a method's body is usually written in a way that makes
assumptions about how that method is combined with the others.

Instead my instinct would be to try and move away from specifying the
combination in the `defgeneric` and instead make it possible to
define new qualifiers for the "one and only" method combination.

E.g. offer some way to define `:append` as a new qualifier such that

(defmethod foo :append (<args>) <body>)

becomes a kind of shorthand for

(defmethod foo (<args>) (append <body> (call-next-method)))

I must admit that I don't know how that would work in general, tho
(e.g. how to specify which mix of qualifiers can be used in the same
`defmethod` and how they're composed, or how the qualifiers affect the
sorting/ordering of methods, ...).


Stefan
0 new messages