Partial template application
bearophile
bearophileHUGS at lycos.com
Mon Jan 31 10:45:21 PST 2011
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
More information about the Digitalmars-d
mailing list