4 ms·
> Java, Python and C++ require Visitor machinery that you ahev to write, for each case, to implement multiple dispatch (and Visitor only works for double dispat
by jcelerier 6y ago
> Java, Python and C++ require Visitor machinery that you ahev to write, for each case, to implement multiple dispatch (and Visitor only works for double dispatch, if you want more than 2 arguments you need even more boilerplate). Julia and CLOS essentially have that machinery built in.
we're in 2020
using value = std::variant<int, float, string>;
void foo(value a, value b, value c) {
struct {
void operator(int, float, string) { }
void operator(float, int, string) { }
void operator(float, string, int) { }
///... etc...
} visitor;
std::visit(visitor, a, b, c);
}
works fine (and has worked fine since a long time with either boost.variant or in C++11 with eggs.variant, etc...)
- codr7 6y agoWell, you can write Fortran in any language. It's far from the same thing though, less convenient and less flexible. Multiple dispatch doesn't require a centralized declaration of the possible types and allows putting implementations in different files.
- tsimionescu 6y agoSure, it's 2020 and you have less boilerplate to write. It's still a little more than Julia or CL. Also, Java doesn't have anything similar in the std lib as far as I know. More importantly, this is not as powerful as true multiple dispatch like in CLOS. There is no way to call other methods, there is no way to specialize partially (e.g. combine the variant with subtypes, and define methods only for some combinations of subtypes and super types on the parameters, and allow the implementation to choose the most specific one). Edit: to add a few more details on my second point. CLOS (and I assume Julia too) allows you to call 'parent' implementations from a child implementation, similar to calling base type methods in virtual dispatch - you can call the next-most-specific method that would have matched the params, which you can't with the visitor. Also, say I have a generic function F(Foo, Bar). I could define methods for F(FooSubtype1, Bar) and F(Foo, BarSubtype1), and then call F(FooSubtype1() , BarSubtypeOfSubtype1() ) and have the right implementation get called (F(Foo, BarSubtype1)).