www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Extend types with free functions as methods

reply Quirin Schroll <qs.il.paperinik gmail.com> writes:
Someone asked about that and I cannot find the thread anymore. 
The goal was to write something so that one can pass an object of 
some type to a function that expects it to have certain methods. 
Sometimes, the functionality of the methods can be implemented 
using free functions, but if the function to be called lies in 
another module, how would it know of those free functions? UFCS 
only works with the functions in scope.

I tried to implement that and got some results. I called it 
`subjoin`.

For example, you'd write it as `func(arg.subjoin!(f1, f2))` when 
`f1` and `f2` are "missing" as methods of `arg`.

Have a look at the code: https://run.dlang.io/is/7dx1F1

```D
void rangeExpectingFunction(Range)(Range range)
{
     import std.stdio;
     for (; !range.empty; range.popFront)
         writeln(range.front);
}

void main()
{
     import std.range.primitives : empty, front, popFront;
     [ 1, 2, 3 ].subjoin!(empty, front, 
popFront).rangeExpectingFunction;
}
```

I hope the one asking for this finds this or is lead here by 
others.
Dec 19 2021
parent Paul Backus <snarwin gmail.com> writes:
On Sunday, 19 December 2021 at 21:53:09 UTC, Quirin Schroll wrote:
 Someone asked about that and I cannot find the thread anymore. 
 The goal was to write something so that one can pass an object 
 of some type to a function that expects it to have certain 
 methods. Sometimes, the functionality of the methods can be 
 implemented using free functions, but if the function to be 
 called lies in another module, how would it know of those free 
 functions? UFCS only works with the functions in scope.
I implemented something like this a while ago and put it up on code.dlang.org as `addle`: https://code.dlang.org/packages/addle Example usage, from the README: ```d import addle; import std.range; // Import a type from another module import mylib: MyStruct; // Define range primitives for MyStruct bool empty(MyStruct a) { return false; } string front(MyStruct a) { return "ok"; } void popFront(MyStruct a) {} // MyStruct isn't considered an input range, because // std.range can't see our UFCS methods. static assert(isInputRange!MyStruct == false); // ...but extending it makes those methods visible. static assert(isInputRange!(Extended!MyStruct)); void main() { import std.range: take, only; import std.algorithm: equal; MyStruct myStruct; // Now we can use all of the standard range algorithms assert( myStruct.extended .take(3) .equal(only("ok", "ok", "ok")) ); } ```
Dec 19 2021