Functional languages often have built-in partial function application:
http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application

D doesn't have this feature built-in despite it can't break C compatibility, 
maybe because it's a lot of work to implement, maybe because it is seen as 
bug-prone, or maybe just because Walter was/is not interested in it.

So in D you do it using std.functional.curry (I think this is a partial 
application more than a currying, so I am not sure this is the best name):

int fun(int a, int b) { return a + b; }
alias curry!(fun, 5) fun5;
assert(fun5(6) == 11);


Few hours ago in D.learn Simen Kjaeraas has shown a small D2 program that uses 
nested templates to allow template partial application:


import std.typecons, std.functional, std.array;

template optArg(alias pred) {
    template optArg(alias fn) {
        auto optArg(Range)(Range r) {
           alias binaryFun!pred predicate;
           alias unaryFun!fn func;

           auto result = tuple(r.front, func(r.front));
           foreach (e; r) {
              auto tmp = func(e);
              if (predicate(e, result[1]))
                 result = tuple(e, tmp);
           }
           return result;
        }
    }
}
void main() {
    alias optArg!"a < b" minArg;
    alias minArg!"a" foo;
    assert(foo([5, 2, 1, 3]) == tuple(1, 1));
}


I'd like a new template feature in D, automatic partial template application. 
It allows to simplify that code like this (untested):

import std.typecons, std.functional, std.array;

auto optArg(alias pred, alias fn, Range)(Range r) {
    alias binaryFun!pred predicate;
    alias unaryFun!fn func;

    auto result = tuple(r.front, func(r.front));
    foreach (e; r) {
        auto tmp = func(e);
        if (predicate(e, result[1]))
            result = tuple(e, tmp);
    }
}

void main() {
    alias optArg!"a < b" minArg;
    alias minArg!"a" foo;
    assert(foo([5, 2, 1, 3]) == tuple(1, 1));
}


If (as usual) you don't want to implement this as a new D feature, I presume 
something like a PartialTemplate/StaticCurry/StaticPartialApplication is 
writeable in the standard library:

import std.typecons, std.functional, std.array;

auto optArg(alias pred, alias fn, Range)(Range r) {
    alias binaryFun!pred predicate;
    alias unaryFun!fn func;

    auto result = tuple(r.front, func(r.front));
    foreach (e; r) {
        auto tmp = func(e);
        if (predicate(e, result[1]))
            result = tuple(e, tmp);
    }
}

void main() {
    alias PartialTemplate!(optArg, "a < b") minArg;
    alias PartialTemplate!(minArg, "a") foo;
    assert(foo([5, 2, 1, 3]) == tuple(1, 1));
}

Bye,
bearophile

Reply via email to