
A polyglot's guide to multiple dispatch – part 3 - ingve
http://eli.thegreenplace.net/2016/a-polyglots-guide-to-multiple-dispatch-part-3/
======
ugexe
Perl 6 makes calling sets of methods[0] easy as well:

    
    
        role Foo { multi method go { 1 } }
        role Bar { multi method go { 2 } }
        my $t = (class :: { }).new;
    
        $t does Foo;
        say $t.*go;  # (1)
    
        $t does Bar;
        say $t.*go;  # (2, 1)
    

[0]:
[https://design.perl6.org/S12.html#Calling_sets_of_methods](https://design.perl6.org/S12.html#Calling_sets_of_methods)

------
asaileanu
Links to the previous parts HN discussions :

Part 1 :
[https://news.ycombinator.com/item?id=11526923](https://news.ycombinator.com/item?id=11526923)

Part 2 :
[https://news.ycombinator.com/item?id=11541526](https://news.ycombinator.com/item?id=11541526)

------
reikonomusha
I mostly liked this article to show some of the basic features of CLOS, but
was a little disappointed about the attitude toward the end. The attitude
toward some of the more advanced features of CLOS like method combination
reminds me of the attitude that some people have for functional programming.
"Well, it's cool you can 'map' and 'reduce' a function across a list, but why
not just use a for-loop?" I think most people on HN can see why that may not
be a good attitude to have because of the larger implications of functional
programming.

Method combination has an overarching theory behind it. My take is as follows:
Methods are by definition associated with a set of constraints on the
arguments. The constraints are, for the most part, specified by their class.
Because classes form a mathematical lattice, we have the notion of "more and
less specifically applicable methods" for a set of arguments, and so the
aforementioned constraints can be ordered and usually the most specific method
is called, as the article explains. But the key thing to notice here is that
if we remove the notion of "more or less applicable", and replace it with just
the notion of "applicable", then we can do some interesting things.

For a particular generic function (Lisp parlance for a method with unspecified
constraints), and for a given set of arguments to the function, there is a set
of applicable methods. How we arrange to execute these applicable methods, and
how we arrange to use the results of the executions, is what constitutes
method combination.

There are two trivial ways to arrange what gets executed. The popular way is
to just execute the most specific only. The other trivial way is to just
execute everything. Many kinds of non-default method combinations (like the
LIST method combination) do this. Another one, which I find generally more
useful, is the + method combination. (This sums all of the results of the
applicable methods. One usual example is calculating prices with additive
taxes.)

Many problems can be decomposed into one which sounds like the following: 1.
Classify your objects into a (multiple-inheritance) class hierarchy. 2. Write
down the behavior that is applicable to products of these objects.

If you can do 1 & 2, then these aspects of CLOS and method combination can
solve your problem in a clean way.

* * *

There were a few nits I had with the article otherwise. What he calls "forms"
are not forms. "Forms" are memory representations of the syntax. The syntax is
called "symbolic expressions" or "S-expressions" or "S-exprs". An even more
pedantic nit is that IF is not called a "special form", it is called a
"special operator". The combination of a special operator and its arguments
make a "special form". (But who cares. Even seasoned Lispers say "special
form" for operators.)

~~~
GregBuchholz
I wonder if anyone has a favorite example that uses method combinations, or
auxiliary methods (:before, :after, :around), or something MOP related.
Preferably one that is "in-the-wild" and not invented just to showcase the
feature.

~~~
batspace
At work we have a condition (think: exception) hierarchy that uses multiply
inherited mixins. One might be validation-failure and introduce a slot telling
you the invalid value. Another might be user-error that records the user that
triggered the error. A third might carry an RPC error code for use if reported
over RPC.

I used a generic function with list combination to collect from the mixins
only the slots that should be reported over RPC. The user is not among them
since it is always reported to the user that triggered the error.

~~~
PuercoPop
Seems pretty nifty, would love if you could share a gist [implementation] of
the idea

~~~
spacebat
Ah, it wasn't list, it was append. Though list would be fine if each mixin
contributes no more than one item, I wanted mixins to be able to contribute
more if necessary, so they always return lists which the combination appends
to the result. It also allows them to decide to return nil and behave as
though they were not called at all.

Here's a suitably abstracted implementation of the idea:
[https://gist.github.com/spacebat/dbad3b50684b3a516071abb3757...](https://gist.github.com/spacebat/dbad3b50684b3a516071abb3757dc585)

Yes I am likening RPC programming to dealing with monsters in the darkness.

------
eudox
To provide an example of the utility of method combinations:

I wrote a project skeleton generator[0] whose functionality is provided by
progn-composable plugins, implemented as mixin classes.

Every bit of functionality, like adding a README.md file to a project
skeleton, adding a .gitignore file, adding stub unit tests, etc. is
implemented as a mixin class. A full template inherits[1] all the mixins it
needs.

There is a generic function, render-template[1], that takes a template, some
options, and the target directory, and uses the progn method combination.
Meaning: every method in the chain is called in succession, and each method
adds its own thing to the generated project. The render-template method for
the gitignore mixin adds a .gitignore file, for instance. When render template
is called on an instance of a class that inherits a bunch of template mixins,
it runs all of those mixins in addition to the render-template method of that
class itself (if any).

In a sense, this is basically the entity-component pattern[3] implemented in
the object system itself, with the caveat that you can't have "multiple
instances" of the same component -- you can't inherit a class twice.

[0]: [https://github.com/roswell/mystic](https://github.com/roswell/mystic)

[1]:
[https://github.com/roswell/mystic/blob/2d0fd8e401d50893b4a15...](https://github.com/roswell/mystic/blob/2d0fd8e401d50893b4a15f009dcd3958b7da5e57/templates/library/library.lisp#L17)

[2]:
[https://github.com/roswell/mystic/blob/2d0fd8e401d50893b4a15...](https://github.com/roswell/mystic/blob/2d0fd8e401d50893b4a15f009dcd3958b7da5e57/src/mystic.lisp#L123)

[3]:
[https://en.wikipedia.org/wiki/Entity_component_system](https://en.wikipedia.org/wiki/Entity_component_system)

------
vikiomega9
Are go-lang interfaces borrowed from lisp style multiple dispatch?

