Implementing multiple dispatch

Hi there, I’ve done some research on the possibility of implementing multiple dispatch.

This is a language feature that I know from other languages, like Julia, Clojure, and Common Lisp.

I’ve seen that you do not have a lot of type reflection, so the only possibility to implement it, as I see it, is via Generic_Dispatching_Constructor.

Now, I understand that type reflection is not enabled since it would allow for code that is too hard to statically analyze.

Is this also the case for multiple dispatch (with optional constraints) implemented via Generic_Dispatching_Constructor or is this something else?

I don’t understand why one is allowed and the other not.

Ok, so Ada does not support multiple dispatch/
There are, however ways that you can work around this, such as manually dispatching.

Here is an example of using Generics, defaulting, and overloading to achieve a manual, static dispatching. — Notice how the proper conversion function is selected off of the parameter From_Type, which is defaulted to the type of the incoming value, and To_Type is used as a parameter for the result-type — thus, instantiation with all the various types and overloading on that, allows the compiler to choose the proper conversion based on the context.

You could use that similarly, to build a dispatch (via generic) and then use that to “isolate”/fix the one side and dispatch the other, thus achieving the same effect.

These are two orthogonal problems; the biggest issue you’re going to encounter is that Ada is single-inheritence/single-dispatch. You could, however, use something like the example above to work around that. — It’s not the “static” vs “dynamic” in play, it’s that Ada is designed as single-inheritance.

1 Like

So first thanks for the quick answer.

Second, since you are talking about overloading and the misconception that this the same thing is quite frequent - I just experienced it 10 minutes ago - are we sure we are talking about the same thing?

Timestamped comparison between function overloading and multiple dispatch.

And third: What about Generic_Dispatching_Constructor?

Ada supports a special case of multiple dispatch. It is limited to multi-methods and only the diagonal of the dispatching table can be overridden. Other combinations are hard-wired to Constraint_Error. Example:

   type T is tagged null record;
   function Multi_Method (X, Y, Z : T) return T;

Here Multi_Method has logically a 4D dispatching table (the implementation would likely use a vector). All arguments and the result are from the same class = multi-method. All must have the same tag on dispatch = diagonal elements.

1 Like

MD is customary implemented as a sequence of consecutive dispatches. E.g. double dispatch. It is very crude and error prone but simple to do in Ada. You just replace argument except one with class-wide type. Inside the body you dispatch on one of them and so on.

Generic_Dispatching_Constructor has nothing to do with multiple dispatch. It is a method of type tag to instance conversion.

MD is incredibly difficult to implement consistently. The languages you mentioned do not satisfy the elementary requirement that dispatch never fail at run-time. They implement not MD but rather some arguments pattern matching.

Multi-methods are somewhat simpler because all overriding happens in the same context so the compiler can generate the dispatching table extension and guarantee that all combination of the table’s new plane are defined = overridden or else inherited.

Generic_Dispatching_Constructor is rather simple. In fact we frequently implement it new, rather than use the provided library implementation because tags may require special handling, e.g. when doing networking or plug-ins. You simply define a Register procedure that takes the tag or its equivalent and the construction function to create the instance. The mapping is maintained internally. This is a pretty common practice.

1 Like

Yeah, I have come across the sentiment that all these languages have not implemented it properly.

I am part of a small group of friends, who are into language design and our wise mage does design his own Forth like, that does implement MP in a way that can’t fail at runtime.

I am incredibly stocked :smiley:

1 Like

Multiple Dispatch is one of those features that seem a very logical thing to have, but are very hard to implement and rarely needed in practice. So I think it was a wise decision not to add it to Ada. Most programmers are quite OK with working around not having MD using the Visitor pattern.

Honestly, I think it needs practical application of a feature, to say something like this.

And the whole thing about MP is, that it’s effects comes really out, if you use it as the only way for polymorphism.

So many languages have made the mistake of using MP as an option, while it’s code reuse numbers of Julia (over 30% across its ecosystem, instead of 5-10% of all other languages tested) can only come from consistent use.