View mode: basic / threaded / horizontal-split · Log in · Help
October 18, 2012
Extending library functions
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
Re: Extending library functions
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
Re: Extending library functions
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
Re: Extending library functions
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
Re: Extending library functions
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
Re: Extending library functions
simendsjo:

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

But maybe this will change.

Bye,
bearophile
October 18, 2012
Re: Extending library functions
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
Re: Extending library functions
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
Top | Discussion index | About this forum | D home