Claim (false): Julia isn't multiple dispatch but overloading

Your definition doesn’t agree with the industry-standard meaning of the term. You can see that it’s incorrect without even having to consider multiple arguments or Julia code—it’s wrong already for single dispatch in C++, Java, C#, etc. Let’s consider C++, which makes this particularly easy to show because the virtual keyword on methods allows choosing between static (non-virtual) and dynamic (virtual) dispatch semantics. Here’s an example program:

#include <iostream>
using namespace std;

class Pet {
    public:
        string name;

        string common_name() { return "pet"; }
        virtual string latin_name() { return "animalia"; };

        virtual void describe() {
            string c = common_name();
            string l = latin_name();
            cout << name << " is a " << c << " (" << l << ")" << endl;
        }
};

class Dog : public Pet {
    public:
        string common_name() { return "dog"; }
        virtual string latin_name() { return "canis lupus familiaris"; }
};
class Cat : public Pet {
    public:
        string common_name() { return "cat"; }
        virtual string latin_name() { return "felis catus"; }
};

int main() {
    Dog fido;  fido.name  = "Fido";
    Cat felix; felix.name = "Felix";

    fido.describe();
    felix.describe();

    return 0;
}

If you compile and run this program, here’s what it prints:

Fido is a pet (canis lupus familiaris)
Felix is a pet (felis catus)

The common_name method is statically dispatched because it is non-virtual and the latin_name method is dynamically dispatched because it is virtual:

  • common_name() is “pet” for both pets because the method is selected solely based on the static type of this in the body of describe, which is always Pet.

  • latin_name() is “canis lupus familiaris” for a Dog and “felis catus” for a Cat because the method is selected based on the runtime type of this.

By your definition, these would both be static dispatch since the compiler can easily see that fido is a Dog and felix is a Cat and doesn’t need to actually do any runtime method selection. However, that disagrees with what people in the industry would call this: the non-virtual one is static dispatch (aka “early binding”) and the virtual one is dynamic dispatch (aka “late binding”). It doesn’t matter at all if the compiler actually does a runtime method lookup or not—the behaviors are different, which is what distinguishes them.

Whether dispatch is dynamic or static is a matter of language semantics (behavior), not implementation. It doesn’t matter when or how the actual method lookup is done: static dispatch dictates that one function body is called whereas dynamic dispatch dictates that a different function body is called. It doesn’t matter how it’s implemented, so if you’re looking at the implementation to see if the dispatch is actually done at runtime or not, you’re barking up the wrong tree.

In Julia there is only dynamic dispatch: there is no way to ask for static (non-virtual) dispatch behavior—it is all dynamic, all the time, on all of the arguments. There isn’t even a concept a static type by which one might statically select a method in principle. The fact that the compiler is very good at statically figuring out which method to call is fortunate but irrelevant.

32 Likes