Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending a templated function as an argument to a templated function in D

Tags:

templates

d

dmd

I'm trying to send D's sort function as a template argument to the pipe function. When I use sort without template arguments it works:

import std.stdio,std.algorithm,std.functional;

void main()
{
    auto arr=pipe!(sort)([1,3,2]);
    writeln(arr);
}

However, when I try to use sort with a template argument:

import std.stdio,std.algorithm,std.functional;

void main()
{
    auto arr=pipe!(sort!"b<a")([1,3,2]);
    writeln(arr);
}

I get an error - main.d(5): Error: template instance sort!("b<a") sort!("b<a") does not match template declaration sort(alias less = "a < b",SwapStrategy ss = SwapStrategy.unstable,Range)

Why does it happen? sort!"b<a" works on it's own, and it has the same arguments and return types as sort, so why does pipe accept sort but not sort!"b<a"? And is there a correct syntax for what I try to do?

UPDATE

OK, I've tried to wrap the sort function. The following code works:

import std.stdio,std.algorithm,std.functional,std.array;

template mysort(string comparer)
{
    auto mysort(T)(T source)
    {
        sort!comparer(source);
        return source;
    }
}

void main()
{
    auto arr=pipe!(mysort!"b<a")([1,3,2]);
    writeln(arr);
}

So why doesn't the original version work? is this because of the extra template parameters sort takes?

like image 778
Idan Arye Avatar asked Mar 09 '12 18:03

Idan Arye


1 Answers

Yes it's because of the extra template parameters — specifically the Range parameter. The problem can be reduced to

size_t sort2(alias f, Range)(Range range)
{
    return 0;
}
alias sort2!"b<a" u;

The instantiation sort!"b<a" will fail because the Range is not determined. The function call sort2!"b<a"([1,2,3]) works because the parameter [1,2,3] can tell the compiler the type Range is int[]. This is known as "implicit function template instantiation (IFTI)". But IFTI only works when it is used as a function. In your use case, sort!"b<a" is instantiated without providing all parameters, thus the error.

This can be fixed by making the input a function literal, which is just similar to your mysort solution:

 auto arr = pipe!(x => sort!"b<a"(x))([1,3,2]);

Or you could provide all required template parameters. This makes the code very unreadable though.

auto arr = pipe!(sort!("b<a", SwapStrategy.unstable, int[]))([1,3,2]);
like image 191
kennytm Avatar answered Oct 11 '22 18:10

kennytm