Overloading an external function for use in a separate module

I want to do this (supported by this ), but I hit a tiny problem (irrigate for your less dizziness - no-displeasure).

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 try to overload run and call runrun :

 import mod_a; void run(T:double)(T v) { writeln("Wigglytuff!"); } void main() { runrun(1.0); } 

This code leads to "Jigglypuff!" not “Wigglytuff!”, which makes sense, since the runrun definition can only see the non-specialized unevolved form available to it in its module. I (and the client code), however, would like to see "Wigglytuff" and not "Jigglypuff".

In C ++, I would throw namespace mod_a { ... } around the run specialization to show that client code execution should be considered next to my library code when trying to determine what the runrun call is runrun , greeting the jar of worms that came up with this behavior .

Is there an idiomatic D-way to arrange this so that the run function can be intentionally captured? In particular, I would like to imitate how global C ++ functions behave with specializations.

+7
d d2
source share
3 answers
 //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); } 
+2
source share

In this example, you are creating the mod_a library, so it would be relatively easy to modify it. But I cannot help but think about the situation when you are not the author of the library.

In this case, the actual author of the library will probably be happy that you cannot just do what you are trying to do ... or actively want to support what you are trying to do.

suggests that the library writer wants you to be able to “capture” the function that he uses in his implementation. He or she will probably go differently; I would do.

This is one of the areas where I believe that the encapsulation stories that you linked, and I just read, accurately describes how to achieve the opposite situation of what you want here. This type screams that he needs contract programming.

As the author of the library, I would probably offer you an interface and, possibly, an abstract class, perhaps one or two specific implementations that you could use to accomplish your task. Someone else might add a template or runtime parameter that requires a specific implementation as an argument. However, someone else might add a lazy line delegate to the mix.

(my) conclusion: as the author of the library, there are options to do what you want. If this is not possible with your preferred library, you are likely to finish submitting the function request.

+1
source share

I found a weird way to do this with mixins to move the namespace distorted from library code to user code. From the perspective of a writer library, this is one additional function and one additional type of template; from the user's point of view, this is one additional (somewhat annoying) line of code along with one additional function call per type instance with global "methods" outside its module. Given that this is a way to explicitly redefine a language function, I think this is very good.

 module wrappers; mixin template wrapmix() { struct Wrap(T) { T* val; auto opDispatch(string Name, A...) { return mixin("(*val)."~Name~"(a);"); } } auto wrap(T)(ref T val) { return Wrap!T(&val); } } 

It is then used to create a type that runs in any module that has been declared for dispatch.

 import mod_a; import wrappers; mixin wrapmix; ///< magic void main() { double val = 1.0; runrun(wrap(val)); ///< note the 'wrap' call } 

Although the code above has not been explicitly tested, I tested the general approach to GDC and seems to work.

Oh, and there is a flaw that, as written, only processes lvalue links, but can be fixed with wrap overloads in the wrappers module.

0
source share

All Articles