• Re: Unusual method combinations

    From Lieven Marchand@21:1/5 to Spiros Bousbouras on Wed Jun 1 21:36:30 2022
    Spiros Bousbouras <spibou@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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Spiros Bousbouras@21:1/5 to All on Wed Jun 1 19:19:46 2022
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Zyni=20Mo=C3=AB?=@21:1/5 to Spiros Bousbouras on Wed Jun 1 21:30:05 2022
    Spiros Bousbouras <spibou@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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Zyni=20Mo=C3=AB?=@21:1/5 to no_email@invalid.invalid on Wed Jun 1 21:32:32 2022
    Zyni Moë <no_email@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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Spiros Bousbouras@21:1/5 to All on Wed Jun 1 23:49:02 2022
    On Wed, 1 Jun 2022 21:30:05 -0000 (UTC) Zyni Moë wrote:
    Spiros Bousbouras <spibou@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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Didier Verna@21:1/5 to All on Thu Jun 2 10:50:33 2022
    Spiros Bousbouras <spibou@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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Zyni=20Mo=C3=AB?=@21:1/5 to Spiros Bousbouras on Thu Jun 2 10:01:15 2022
    Spiros Bousbouras <spibou@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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Spiros Bousbouras@21:1/5 to Lieven Marchand on Fri Jun 3 18:52:59 2022
    On Wed, 01 Jun 2022 21:36:30 +0200
    Lieven Marchand <mal@wyrd.be> wrote:
    Spiros Bousbouras <spibou@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 ?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Spiros Bousbouras@21:1/5 to Didier Verna on Fri Jun 3 19:03:46 2022
    On Thu, 02 Jun 2022 10:50:33 +0200
    Didier Verna <didier@lrde.epita.fr> wrote:
    Spiros Bousbouras <spibou@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.'
    "Use of weapons" by Iain Banks

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Zyni=20Mo=C3=AB?=@21:1/5 to Spiros Bousbouras on Fri Jun 3 19:24:30 2022
    Spiros Bousbouras <spibou@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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lieven Marchand@21:1/5 to Spiros Bousbouras on Fri Jun 3 21:29:30 2022
    Spiros Bousbouras <spibou@gmail.com> writes:

    On Wed, 01 Jun 2022 21:36:30 +0200
    Lieven Marchand <mal@wyrd.be> wrote:
    Spiros Bousbouras <spibou@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 ?

    https://cliki.net/Design%20by%20contract

    --
    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Spiros Bousbouras@21:1/5 to All on Fri Jun 3 19:49:17 2022
    On Thu, 2 Jun 2022 10:01:15 -0000 (UTC) Zyni Moë wrote:
    Spiros Bousbouras <spibou@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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Zyni=20Mo=C3=AB?=@21:1/5 to Spiros Bousbouras on Fri Jun 3 21:52:15 2022
    Spiros Bousbouras <spibou@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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Didier Verna@21:1/5 to Spiros Bousbouras on Sat Jun 4 11:32:03 2022
    Spiros Bousbouras <spibou@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/

    --
    Resistance is futile. You will be jazzimilated.

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Monnier@21:1/5 to All on Sat Jun 4 13:47:31 2022
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)