www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - std.functional.compose() design

This D2 program comes (with few changes) from rosettacode site, it shows a
simple example of function composition:



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:



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));
}



std.functional.compose may be reconsidered.

Bye,
bearophile
Aug 19 2010