std.functional.compose() design
bearophile
bearophileHUGS at lycos.com
Thu Aug 19 19:41:47 PDT 2010
This D2 program comes (with few changes) from rosettacode site, it shows a simple example of function composition:
// program #1
import std.stdio: writefln;
private import std.math;
T delegate(S) compose(T, U, S)(T delegate(U) f, U delegate(S) g) {
return (S s) { return f(g(s)); };
}
void main() {
auto sin = (real x) { return std.math.sin(x); };
auto asin = (real x) { return std.math.asin(x); };
auto cos = (real x) { return std.math.cos(x); };
auto acos = (real x) { return std.math.acos(x); };
auto cube = (real x) { return x ^^ 3; };
auto cbrt = (real x) { return std.math.cbrt(x); };
auto fun = [sin, cos, cube];
auto inv = [asin, acos, cbrt];
foreach (i, f; fun)
writefln("%6.3f", compose(f, inv[i])(0.5));
}
In Phobos2 there is a compose(), but it takes the functions as template arguments, so you can't just use:
foreach (i, f; fun)
writefln("%6.3f", compose!(f, inv[i])(0.5));
You need to use (ugly) TypeTuples of delegates, a static foreach and a bit of template blot caused by the static foreach:
// program #2
import std.stdio: writefln;
private import std.math;
import std.functional: compose;
import std.typetuple: TypeTuple;
void main() {
// wrappers needed as not all built-in functions
// have same signature, eg pure/nothrow
auto sin = (real x) { return std.math.sin(x); };
auto asin = (real x) { return std.math.asin(x); };
auto cos = (real x) { return std.math.cos(x); };
auto acos = (real x) { return std.math.acos(x); };
auto cube = (real x) { return x ^^ 3; };
auto cbrt = (real x) { return std.math.cbrt(x); };
alias TypeTuple!(sin, cos, cube) dir;
alias TypeTuple!(asin, acos, cbrt) inv;
foreach (i, f; dir)
writefln("%6.3f", compose!(f, inv[i])(0.5));
}
Is the usage of compose of program #1 common? If so the design of std.functional.compose may be reconsidered.
Bye,
bearophile
More information about the Digitalmars-d-learn
mailing list