August 02, 2012
On 8/2/12, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
> On 8/2/12, Walter Bright <newshound2@digitalmars.com> wrote:
>> Known issue, it's an inevitable result (it never worked right anyway):
>>
>> http://d.puremagic.com/issues/show_bug.cgi?id=8454
>>
>> P.S. You might want to monitor the beta releases.
>>
>
> I've posted about that exact Derelict case in Issue 3866 during the betas, but nobody replied.
>
> But a library solution could be made if one wants to use an inner alias. Maybe we even have one in Phobos? Something like:
>
> void foo(void delegate(string s, bool isTrue) dg)
> {
>     alias DefVal!(dg, true) deg;
>     // use deg as if it were dg() with default for 'isTrue'
> }
>
> Not the most readable code.. but it's similar to curry (except
> backwards) I guess.
>

So here's an implementation:

import std.stdio;
import std.traits;
import std.typetuple;

template DefVal(alias Call, DefVals...)
    if (isCallable!Call && DefVals.length <= ParameterTypeTuple!Call.length)
{
    auto DefVal(T...)(T args)
    {
        return Call(args, Reverse!DefVals);
    }
}

void foo(int x, float y, string z)
{
    writefln("x: %s, y: %s, z: %s", x, y, z);
}

void main()
{
    alias DefVal!(foo, "a", 1.0, 1) fooDef3;
    alias DefVal!(foo, "a", 1.0) fooDef2;
    alias DefVal!(foo, "a") fooDef1;
    alias DefVal!(foo) fooDef0;

    fooDef0(1, 1.0, "a");
    fooDef1(1, 1.0);
    fooDef2(1);
    fooDef3();
}

Essentially it's like the reverse of curry().