>I don't understand what problem the author is trying to solve here - maybe it's language specific? More related to dynamic typing and efficient dispatch?

The expression problem only arises in statically typed programming languages, it does not exist in dynamically typed programming languages.

Operating overloading has nothing to do with the problem and can not be used to resolve it. Operators are nothing more than a one-off syntax so we can use familiar childhood notation like a + b, etc... they are not particularly meaningful. The ability to overload operators or functions in general is also irrelevant since such overloads are resolved statically at compile time.

> The expression problem only arises in statically typed programming languages, it does not exist in dynamically typed programming languages.

Wadler's list of requirements for solving the expression problem include "with static checking that all cases are covered", so in one sense, yes, dynamic languages don't have this "problem". But in another sense, dynamic languages simply have no chance to solve the problem because they don't statically check anything.

It is true that it's much easier to do multiple dispatch and open-ended extension in dymamic languages. That's a nice benefit of them. But you do sacrifice all of the safety, code navigation, and performance of static types in order to get that.

The problem Wadler is trying to solve is "how can we have this sort of open-ended extension in both directions without giving up static safety?"

This isn't true. Julia manages to maintain good performance with multiple dispatch through lots of type inference in the compiler (and carefully written code in the language to preserve "type stability")

Yes, Julia is an interesting outlier in the design space. My understanding is that Julia gets the speed it has largely by JITting a lot of code for every instantation of a generic/dynamic function that it sees with all of the concrete incoming types.

That's an interesting point in the design space where you get the flexibility of dynamic types (and multiple dispatch!) and good runtime speed. But you pay for it with slower startup times, less predictable performance, and much higher memory usage. You are also married to a JIT. Julia really is designed to be run interactively in a REPL from source. The language isn't well-suited to compiling a standalone executable ahead of time. That makes perfect sense for its use cases, but would make it a challenge to adopt in other use cases.

(For example, I work on Dart which is mostly used for building mobile apps. That means we care deeply about executable size, startup speed, and the ability to compile ahead-of-time to native executables.)

> does not exist in dynamically typed programming languages

The "problem" exists for dynamically-typed languages as well. If you define a new class in Python, you still need to teach existing code how to operate on it (though you might be using inheritance to automatically derive some of those implementations, but inheritance obviously isn't limited to dynamic languages).

> Operating overloading has nothing to do with the problem

You've got T types (some new), and O operators (some new) and want to implement all operators for all types ... This is the exact definition of operator overloading.

There is no magic (other than inheritance or generics, if applicable) that will remove the need to individually implement all those O x T cases, and while that is obviously necessary, it is also all that you need to do.

If you are not talking about operator overloading - supporting the same operator for multiple different custom types, then what are you talking about ?!