I want to do this (supported by this), but I'm hitting a tiny issue (watered down for your less-headachy-non-displeasure).
Let's say I'm a library writer, and I have these functions in a D file:
module mod_a;
import std.stdio;
void run(T)(T v) { writeln("Jigglypuff!"); }
void runrun(T)(T v) { run(v); }
And I have client code in another module in which I attempt to overload run
and call runrun
:
import mod_a;
void run(T:double)(T v) { writeln("Wigglytuff!"); }
void main() { runrun(1.0); }
This code results in 'Jigglypuff!' being printed rather than 'Wigglytuff!', which makes sense, because the definition of runrun
can only see the unevolved unspecialized form available to it in its module. I (and client code), however, would like to be seeing a 'Wigglytuff' rather than a 'Jigglypuff'.
In C++ I'd throw a namespace mod_a { ... }
around the specialization of run to show that the client code's run should be examined alongside my library code when trying to determine what the definition of runrun
calls, welcoming the can of worms that came along with such behavior.
Is there an idiomatic D-way to organize this such that the function run
may be intentionally hijacked? Specifically, I'd like to mimic the way C++'s global functions behave with ad-hoc specializations.
//untested
module mod_a;
import std.stdio;
void run(T)(T v) if (!is(T : double)) { writeln("Jigglypuff!"); }
void runrun(T)(T v) { run(v); }
import mod_a;
void run(T)() if (is(T : double)) { writeln("Wigglytuff!"); }
void main() { runrun(1.0); }
In this example you are the authoring the library mod_a
so it would be relatively easy to modify it. But I can't help but think about the situation where you aren't the author of the library.
In which case the actual author of the library would probably either be happy that you cannot just do what you are trying to do... or actively wants to support what you are trying to do.
lets assume the library writer wants you to be able to "hijack" a function that he/she uses in his implementation. He or she would probably go about it differently; I would.
This is one area where I believe the encapsulation stories you linked and I just read describe exactly how to achieve the opposite situation of what you want here. This type of thing screams that it needs contract programming.
As a library author, I'd probably offer you an interface and possibly an abstract class, maybe even one or two concrete implementations, that you could use to do your thing. Someone else might give add a template or runtime parameter requiring a specific implementation as an argument. Yet someone else could add a lazy string delegate to the mix.
(my) conclusion: As a library author, there are options to make what you want possible. If it's not possible with your preferred library you'll probably end up filing a feature request.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With