www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to create a custom max() function without the ambiguity error.

reply realhet <real_het hotmail.com> writes:
Hi,

I'm trying to use a popular function name "max", and extend it 
for my special types:

For example:

module utils;
MyType max(in MyType a, in MyType a){...}  //static function

struct V3f{
   V3f max(in V2f b){...} //member function
}

module gl3n;
vec3 max(in vec3 a, in vec3 a) //another static function in 
different module

I also want to use std.algorithm.comparison.max as well.


I know that the ambiguity error can be avoided by public 
importing all the various max implementations into one place, but 
how to do this when I want to use 3 modules? Need a 4th module to 
combine them all? Is there a nicer way?
Another question that is it possible to extend the the template 
function "to" in more than one module and use it easily from my 
main project modules?
Dec 06 2019
next sibling parent reply Ferhat =?UTF-8?B?S3VydHVsbXXFnw==?= <aferust gmail.com> writes:
On Friday, 6 December 2019 at 12:34:17 UTC, realhet wrote:
 Hi,

 I'm trying to use a popular function name "max", and extend it 
 for my special types:

 For example:

 module utils;
 MyType max(in MyType a, in MyType a){...}  //static function

 struct V3f{
   V3f max(in V2f b){...} //member function
 }

 module gl3n;
 vec3 max(in vec3 a, in vec3 a) //another static function in 
 different module

 I also want to use std.algorithm.comparison.max as well.


 I know that the ambiguity error can be avoided by public 
 importing all the various max implementations into one place, 
 but how to do this when I want to use 3 modules? Need a 4th 
 module to combine them all? Is there a nicer way?
 Another question that is it possible to extend the the template 
 function "to" in more than one module and use it easily from my 
 main project modules?
how about this: import std.stdio; import std.algorithm.comparison: max1 = max; int max(int a, int b){ // dummy max return 5; } void main(){ int a = 2; int b = 3; max1(a, b).writeln; // writes 3 }
Dec 06 2019
parent reply realhet <real_het hotmail.com> writes:
On Friday, 6 December 2019 at 13:04:57 UTC, Ferhat Kurtulmuş 
wrote:
 On Friday, 6 December 2019 at 12:34:17 UTC, realhet wrote:
 Hi,

 I'm trying to use a popular function name "max", and extend it 
 for my special types:

 For example:

 module utils;
 MyType max(in MyType a, in MyType a){...}  //static function

 struct V3f{
   V3f max(in V2f b){...} //member function
 }

 module gl3n;
 vec3 max(in vec3 a, in vec3 a) //another static function in 
 different module

 I also want to use std.algorithm.comparison.max as well.


 I know that the ambiguity error can be avoided by public 
 importing all the various max implementations into one place, 
 but how to do this when I want to use 3 modules? Need a 4th 
 module to combine them all? Is there a nicer way?
 Another question that is it possible to extend the the 
 template function "to" in more than one module and use it 
 easily from my main project modules?
how about this: import std.stdio; import std.algorithm.comparison: max1 = max; int max(int a, int b){ // dummy max return 5; } void main(){ int a = 2; int b = 3; max1(a, b).writeln; // writes 3 }
Thx for answering! This is what I want to avoid: To use extra identifiers or imports for the same semantic task. ------------------------ module m1; public import std.algorithm.comparison: max; struct MyType{ int x;} MyType max(in MyType a, in MyType a){ return a.x>b.x ? a : b; } module main; import m1; ------------------------ From here: the max() is working for MyType and also for the types supported by std.algo.comparison.max. BUT! What if I want to import another module which is overloading max?! It will be an ambiguity between m1 and the other module. I'm searching for a clever solution, not just manually reimporting everything in every module where I use multiple modules which also manually reimporting those simple names like 'max'.
Dec 06 2019
parent reply Ferhat =?UTF-8?B?S3VydHVsbXXFnw==?= <aferust gmail.com> writes:
On Friday, 6 December 2019 at 13:25:24 UTC, realhet wrote:
 On Friday, 6 December 2019 at 13:04:57 UTC, Ferhat Kurtulmuş 
 wrote:
 [...]
Thx for answering! [...]
In d you can also use scoped imports: https://dlang.org/spec/module.html#scoped_imports
Dec 06 2019
parent reply realhet <real_het hotmail.com> writes:
On Friday, 6 December 2019 at 14:55:18 UTC, Ferhat Kurtulmuş 
wrote:
 On Friday, 6 December 2019 at 13:25:24 UTC, realhet wrote:
 On Friday, 6 December 2019 at 13:04:57 UTC, Ferhat Kurtulmuş 
 wrote:
 [...]
Thx for answering! [...]
In d you can also use scoped imports: https://dlang.org/spec/module.html#scoped_imports
Yea, I know about that. I also read the documentation about module imports, but in reality it feels like a bit different. Here's my latest attempt on EXTENDING std.algorithm.max's functionality with a max operation on a custom type. The type is the GLSL vec2 type which does the max operation component-wise. The D std implementation uses the < operator, but with overriding that for my custom type it is impossible to realise. -> max(vec2(1, 2), vec2(2,1)) == vec2(2,2) //So here is my helper module: ----------------------------------------------------- module testimport_a; import std.algorithm; struct vec2{ float x, y; } auto max(in vec2 a, in vec2 b){ return vec2(max(a.x, b.x), max(a.y, b.y)); } import std.algorithm: max; // and the main module //////////////////////////////// module testimport_main; import std.stdio, testimport_a; void main(){ auto a = vec2(1, 2), b = vec2(0, 5); max(a, b).writeln; max(1, 2).writeln; } ------------------------------------------------------ Both of the max instructions are working nicely. But here are all the things/restrictions which aren't as nice: - in the imported module it is really important, to put my max() function BEFORE the std one. The std implementation tries to serve EVERYTHING, but it fails the compilation when it check the < operator (which is non-existent on 2d vectors). - It doesn't matter if I use public import or not. When it finds any compatible max() inside the helper unit's functions, and its imported functionst that are specified by name, it will compile it. - It is really important to import the original max() by name. (After my narrower max()) - If I import std.algorithm in the main module, no matter the order, it will fail. As the std.algorithm.max alone is unable to serve vec2 types. - I tried to make one more module, to be able to use max on vec2, vec3 and everything else, but I failed. none of the my random guessing worked.
Dec 06 2019
parent Mike Parker <aldacron gmail.com> writes:
On Friday, 6 December 2019 at 21:02:53 UTC, realhet wrote:

 Here's my latest attempt on EXTENDING std.algorithm.max's 
 functionality with a max operation on a custom type.
 The type is the GLSL vec2 type which does the max operation 
 component-wise.
 The D std implementation uses the < operator, but with 
 overriding that for my custom type it is impossible to realise. 
 -> max(vec2(1, 2), vec2(2,1)) == vec2(2,2)
The reason you're having so much trouble with this is that you're violating the contract of max. It's a template, so it's already set up to work with custom types without any need to write a custom max function, as long as the types adhere to the contract. Consider other functions in std.algorithm, such as sort or equal, that allow you to pass a custom predicate. max doesn't have that because, by defintion, there is only one comparison for it to do:
. Any type that doesn't support that isn't going to work with 
max. Moreover, your return value violates the function's contract: "Iterates the passed arguments and return the maximum value." You aren't returning the maximum value. You're returning a new value constructed from the maximum components of the two parameters. That is not the same behavior as max(1, 3). Given that your function has a different contract, it should also have a different name.
Dec 06 2019
prev sibling parent Andrea Fontana <nospam example.com> writes:
On Friday, 6 December 2019 at 12:34:17 UTC, realhet wrote:
 Hi,

 I'm trying to use a popular function name "max", and extend it 
 for my special types:

 For example:

 module utils;
 MyType max(in MyType a, in MyType a){...}  //static function

 struct V3f{
   V3f max(in V2f b){...} //member function
 }

 module gl3n;
 vec3 max(in vec3 a, in vec3 a) //another static function in 
 different module

 I also want to use std.algorithm.comparison.max as well.


 I know that the ambiguity error can be avoided by public 
 importing all the various max implementations into one place, 
 but how to do this when I want to use 3 modules? Need a 4th 
 module to combine them all? Is there a nicer way?
 Another question that is it possible to extend the the template 
 function "to" in more than one module and use it easily from my 
 main project modules?
What about: int max(int a, int b){ return 0; } void main() { .max(3,4).writeln; // 0 std.algorithm.comparison.max(3,4).writeln; // 4 }
Dec 06 2019