Thread overview
Extending library functions
Oct 18, 2012
tn
Oct 18, 2012
simendsjo
Oct 18, 2012
tn
Oct 18, 2012
simendsjo
Oct 18, 2012
tn
Oct 18, 2012
bearophile
Oct 18, 2012
Jonathan M Davis
Oct 18, 2012
Jacob Carlborg
October 18, 2012
Hi.

I want to extend math library functions to work with my own type. However, the definition for my own type seems to prevent automated access to the original function. How can I fix this unexpected behavior?

Simplified example:
--------------------
import std.math;

int exp2(int x) {
    return 1 >> x;
}

void main() {
    assert(exp2(0.0) == 1.0);              // <= why does not this work anymore?
    //assert(std.math.exp2(0.0) == 1.0);   // <= this works
}
--------------------

October 18, 2012
On Thursday, 18 October 2012 at 11:31:47 UTC, tn wrote:
> Hi.
>
> I want to extend math library functions to work with my own type. However, the definition for my own type seems to prevent automated access to the original function. How can I fix this unexpected behavior?
>
> Simplified example:
> --------------------
> import std.math;
>
> int exp2(int x) {
>     return 1 >> x;
> }
>
> void main() {
>     assert(exp2(0.0) == 1.0);              // <= why does not this work anymore?
>     //assert(std.math.exp2(0.0) == 1.0);   // <= this works
> }
> --------------------

You need to manually add std.math.exp2 to the overload set so importing external methods doesn't hijack your methods:
http://dlang.org/function.html#overload-sets

alias std.math.exp2 exp2;

October 18, 2012
On Thursday, 18 October 2012 at 11:43:40 UTC, simendsjo wrote:
> On Thursday, 18 October 2012 at 11:31:47 UTC, tn wrote:
>> Hi.
>>
>> I want to extend math library functions to work with my own type. However, the definition for my own type seems to prevent automated access to the original function. How can I fix this unexpected behavior?
>>
>> Simplified example:
>> --------------------
>> import std.math;
>>
>> int exp2(int x) {
>>    return 1 >> x;
>> }
>>
>> void main() {
>>    assert(exp2(0.0) == 1.0);              // <= why does not this work anymore?
>>    //assert(std.math.exp2(0.0) == 1.0);   // <= this works
>> }
>> --------------------
>
> You need to manually add std.math.exp2 to the overload set so importing external methods doesn't hijack your methods:
> http://dlang.org/function.html#overload-sets
>
> alias std.math.exp2 exp2;

Thanks, that clarifies quite a lot. Unfortunately my example was too simplified, as my type is a template.

This still does not work:
--------------------
import std.math;

struct Lognum(T) {
	T lx;
}

T log(T)(Lognum!T x) {
	return x.lx;
}

alias std.math.log log;

void main() {
	//assert(std.math.log(1.0) == 0.0);
	assert(log(1.0) == 0.0);
	Lognum!double x;
	x.lx = 0.0;
	assert(log(x) == 0.0);
}
--------------------

October 18, 2012
On Thursday, 18 October 2012 at 12:10:17 UTC, tn wrote:
> On Thursday, 18 October 2012 at 11:43:40 UTC, simendsjo wrote:
>> On Thursday, 18 October 2012 at 11:31:47 UTC, tn wrote:
>> (...)
>> You need to manually add std.math.exp2 to the overload set so importing external methods doesn't hijack your methods:
>> http://dlang.org/function.html#overload-sets
>>
>> alias std.math.exp2 exp2;
>
> Thanks, that clarifies quite a lot. Unfortunately my example was too simplified, as my type is a template.
>
> This still does not work:
> --------------------
> import std.math;
>
> struct Lognum(T) {
> 	T lx;
> }
>
> T log(T)(Lognum!T x) {
> 	return x.lx;
> }
>
> alias std.math.log log;
>
> void main() {
> 	//assert(std.math.log(1.0) == 0.0);
> 	assert(log(1.0) == 0.0);
> 	Lognum!double x;
> 	x.lx = 0.0;
> 	assert(log(x) == 0.0);
> }
> --------------------

I don't think you can overload template methods with non-template methods:

void f(string i) {}
void f(T)(T i) if (is(T == double)) {}

void main(string[] args) {
    f(2.2);
}

Error: template ol.f(T) if (is(T == double)) conflicts with function ol.f at ol.d(1)
October 18, 2012
On Thursday, 18 October 2012 at 13:35:55 UTC, simendsjo wrote:
> On Thursday, 18 October 2012 at 12:10:17 UTC, tn wrote:
>> On Thursday, 18 October 2012 at 11:43:40 UTC, simendsjo wrote:
>>> On Thursday, 18 October 2012 at 11:31:47 UTC, tn wrote:
>>> (...)
>>> You need to manually add std.math.exp2 to the overload set so importing external methods doesn't hijack your methods:
>>> http://dlang.org/function.html#overload-sets
>>>
>>> alias std.math.exp2 exp2;
>>
>> Thanks, that clarifies quite a lot. Unfortunately my example was too simplified, as my type is a template.
>>
>> This still does not work:
>> --------------------
>> import std.math;
>>
>> struct Lognum(T) {
>> 	T lx;
>> }
>>
>> T log(T)(Lognum!T x) {
>> 	return x.lx;
>> }
>>
>> alias std.math.log log;
>>
>> void main() {
>> 	//assert(std.math.log(1.0) == 0.0);
>> 	assert(log(1.0) == 0.0);
>> 	Lognum!double x;
>> 	x.lx = 0.0;
>> 	assert(log(x) == 0.0);
>> }
>> --------------------
>
> I don't think you can overload template methods with non-template methods:
>
> void f(string i) {}
> void f(T)(T i) if (is(T == double)) {}
>
> void main(string[] args) {
>     f(2.2);
> }
>
> Error: template ol.f(T) if (is(T == double)) conflicts with function ol.f at ol.d(1)

That's too bad. But why then does this work:

--------------------
module a;
void f(string i) {}
--------------------
module b;
void f(T)(T i) if (is(T == double)) {}
--------------------
import a;
import b;

void main(string[] args) {
    f("asdf");
    f(2.2);
}
--------------------
October 18, 2012
simendsjo:

> I don't think you can overload template methods with non-template methods:

But maybe this will change.

Bye,
bearophile
October 18, 2012
On 2012-10-18 15:35, simendsjo wrote:

> I don't think you can overload template methods with non-template methods

You cannot. The usual workaround for this is to make the non-template method a dummy template:

void foo () (int a) {} // Note the extra pair of empty parentheses

But this won't work if you're not controlling the non-template method.

-- 
/Jacob Carlborg
October 18, 2012
On Thursday, October 18, 2012 16:22:17 bearophile wrote:
> simendsjo:
> > I don't think you can overload template methods with
> 
> > non-template methods:
> But maybe this will change.

It's bug (I forget the exact bug number). TDPL says that you can do it, and as I understand it, it's simply a question of when someone is going to fix it (though I have no idea how easy it will be to fix it) and not a question of whether it'll change or not.

- Jonathan M Davis