Global Dispatch
Crosspost from: https://t.me/justy_tylor/4
This article describes Global Dispatch, a new approach for dispatching function calls over a set of specific signatures in programming languages, developed by me some time ago.
Let's start with the notion of types and values. As usual, if we have type A and type B, and every instance of B is also A, then B is a more specific pattern in signatures. Also, multiple inheritance (or multiple interfaces implementation, depending on language capabilities) is supported. There is no sorting order between different "is" facts, so no leaky things like C3 linearization are allowed. Also, there is no specificity for contravariant parameter types.
And here we have the first improvement over traditional approaches. The most specific patterns are values themselves. It can be an enum value or string value, whatever. If you have experience with professional C++ code then you are surely remember lots of cases where types are used instead of enum values. That's not right. It deserves proper fixing.
The next step will be moving to Multiple Dispatch. Dynamic, static, or mixed. The latter two do require compiler support, and dynamic can be performed by a library (in languages with enough dynamic nature or reflections). Here another improvement happens for dynamic dispatch. Collection types are recognized not by their defined covariant type parameters, but by the actual types of items they contain. So variable defined with type List[A] can at some moment consist only of instances of more specific B and will be correctly recognized as List[B]. The importance of this will be shown later.
Final step. We're moving to Global Dispatch. Instead of function parameters, just any reachable identifier can be used in a signature (and checked/specialized between signatures).
Fields of parameters: obj.parent.parent
Global variables: settings.os_version
Values from the outer scope in closures: why_not
Implications.
It's easier to specialize signatures for different environments (operating systems, graphical APIs). No need for C/C++ preprocessors or preprocessing-like features.
Testing made simple. Just write some alternative signatures for mocks with (mode is testing) specialization. No more dark patterns like "dependency injection".
It's easier to define application logic. Checking that the user has selected a list of items "of this specific type" in GUI on one panel and some context on the other panel. Or dispatch of low-level GUI events, where multiple stages of "if click happened in this type of view", "if this instrument was selected at the time", and "if this layer is not read-only" are replaced by simple signatures at once. Or filling menus and toolbars with correctly chosen actions.
When extending applications with plugins. Just define functions with correct signatures and annotations in a plugin, that's it.
And, last but not least, when writing compiler or writing EDSL in some general purpose host language.
Practice.
I have a rough prototype library for Global Dispatch in C#, it contains only features designed for my (compiler-related) needs.
Currently no support for GUI annotations, plugins, etc. But I already did things with GUI annotations and dynamic recognition of List[B] a long time ago (.15926 Editor, 2011), before Global Dispatch. So they are easy to repeat in C# or another (my own?) language.
Also, this approach goes far beyond programming languages. It offers a significant improvement over existing knowledge representation methods, such as RDF+OWL, ISO 15926-2, HQDM, Gellish, and many others. But that subject deserves a separate article.
This article describes Global Dispatch, a new approach for dispatching function calls over a set of specific signatures in programming languages, developed by me some time ago.
Let's start with the notion of types and values. As usual, if we have type A and type B, and every instance of B is also A, then B is a more specific pattern in signatures. Also, multiple inheritance (or multiple interfaces implementation, depending on language capabilities) is supported. There is no sorting order between different "is" facts, so no leaky things like C3 linearization are allowed. Also, there is no specificity for contravariant parameter types.
And here we have the first improvement over traditional approaches. The most specific patterns are values themselves. It can be an enum value or string value, whatever. If you have experience with professional C++ code then you are surely remember lots of cases where types are used instead of enum values. That's not right. It deserves proper fixing.
The next step will be moving to Multiple Dispatch. Dynamic, static, or mixed. The latter two do require compiler support, and dynamic can be performed by a library (in languages with enough dynamic nature or reflections). Here another improvement happens for dynamic dispatch. Collection types are recognized not by their defined covariant type parameters, but by the actual types of items they contain. So variable defined with type List[A] can at some moment consist only of instances of more specific B and will be correctly recognized as List[B]. The importance of this will be shown later.
Final step. We're moving to Global Dispatch. Instead of function parameters, just any reachable identifier can be used in a signature (and checked/specialized between signatures).
Fields of parameters: obj.parent.parent
Global variables: settings.os_version
Values from the outer scope in closures: why_not
Implications.
It's easier to specialize signatures for different environments (operating systems, graphical APIs). No need for C/C++ preprocessors or preprocessing-like features.
Testing made simple. Just write some alternative signatures for mocks with (mode is testing) specialization. No more dark patterns like "dependency injection".
It's easier to define application logic. Checking that the user has selected a list of items "of this specific type" in GUI on one panel and some context on the other panel. Or dispatch of low-level GUI events, where multiple stages of "if click happened in this type of view", "if this instrument was selected at the time", and "if this layer is not read-only" are replaced by simple signatures at once. Or filling menus and toolbars with correctly chosen actions.
When extending applications with plugins. Just define functions with correct signatures and annotations in a plugin, that's it.
And, last but not least, when writing compiler or writing EDSL in some general purpose host language.
Practice.
I have a rough prototype library for Global Dispatch in C#, it contains only features designed for my (compiler-related) needs.
Currently no support for GUI annotations, plugins, etc. But I already did things with GUI annotations and dynamic recognition of List[B] a long time ago (.15926 Editor, 2011), before Global Dispatch. So they are easy to repeat in C# or another (my own?) language.
Also, this approach goes far beyond programming languages. It offers a significant improvement over existing knowledge representation methods, such as RDF+OWL, ISO 15926-2, HQDM, Gellish, and many others. But that subject deserves a separate article.