Report a bug
If you spot a problem with this page, click here to create a GitHub issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.


Functions that manipulate other functions. This module provides functions for compile time function composition. These functions are helpful when constructing predicates for the algorithms in mir.ndslice.


Function Name Description
naryFun Create a unary, binary or N-nary function from a string. Most often used when defining algorithms on ranges and slices.
pipe Join a couple of functions into one that executes the original functions one after the other, using one function's result for the next function's argument.
not Creates a function that negates another.
reverseArgs Predicate that reverses the order of its arguments.
forward Forwards function arguments with saving ref-ness.
tuple Removes Ref shell.
unref Creates a Tuple structure.
_ref Creates a Ref structure.
T[N] staticArray(T, size_t N)(return scope T[N] a...);
Constructs static array.
struct Ref(T) if (!isRef!T);
Simple wrapper that holds a pointer. It is used for as workaround to return multiple auto ref values.
@trusted this(ref T value);
T* __ptr;
inout @property ref inout(T) __value();
const scope bool opEquals(ref scope const T rhs);
const scope bool opEquals(scope const T rhs);
const size_t toHash();
Ref!T _ref(T)(ref T value);
Creates Ref wrapper.
struct Tuple(T...);
Simplified tuple structure. Some fields may be type of Ref. Ref stores a pointer to a values.
template Unref(V : Ref!T, T)

template Unref(V : Tuple!T, T...)

template Unref(V)
Removes Ref shell.
Tuple!Args tuple(Args...)(auto ref Args args);
a Tuple structure.
ref T unref(V : Ref!T, T)(return scope V value);

Unref!(Tuple!T) unref(V : Tuple!T, T...)(V value);

ref V unref(V)(return ref scope V value);

V unref(V)(V value);
Removes Ref shell.
template adjoin(fun...) if (fun.length && (fun.length <= 26))
Takes multiple functions and adjoins them together. The result is a Tuple with one element per passed-in function. Upon invocation, the returned tuple is the adjoined results of all functions.

Note In the special case where only a single function is provided (F.length == 1), adjoin simply aliases to the single passed function (F[0]).

static bool f1(int a) { return a != 0; }
static int f2(int a) { return a / 2; }
auto x = adjoin!(f1, f2)(5);
assert(is(typeof(x) == Tuple!(bool, int)));
assert(x.a == true && x.b == 2);
auto adjoin(Args...)(auto ref Args args);
template naryFun(functions...) if (functions.length >= 1)
Aliases itself to a set of functions.
Transforms strings representing an expression into a binary function. The strings must use symbol names a, b, ..., z as the parameters. If functions[i] is not a string, naryFun aliases itself away to functions[i].
// Strings are compiled into functions:
alias isEven = naryFun!("(a & 1) == 0");
assert(isEven(2) && !isEven(1));
alias less = naryFun!("a < b");
assert(less(1, 2) && !less(2, 1));
alias greater = naryFun!("a > b");
assert(!greater("1", "2") && greater("2", "1"));
naryFun accepts up to 26 arguments.
assert(naryFun!("a * b + c")(2, 3, 4) == 10);
naryFun can return by reference.
int a;
assert(&naryFun!("a")(a) == &a);
args parameter tuple
assert(naryFun!("args[0] + args[1]")(2, 3) == 5);
Multiple functions
alias fun = naryFun!(
    (uint a) => a,
    (ulong a) => a * 2,
    a => a * 3,

int a = 10;
long b = 10;
float c = 10;

assert(fun(a) == 10);
assert(fun(b) == 20);
assert(fun(c) == 30);
template reverseArgs(alias fun)
N-ary predicate that reverses the order of arguments, e.g., given pred(a, b, c), returns pred(c, b, a).
int abc(int a, int b, int c) { return a * b + c; }
alias cba = reverseArgs!abc;
assert(abc(91, 17, 32) == cba(32, 17, 91));
ref auto reverseArgs(Args...)(auto ref Args args)
if (is(typeof(fun(Reverse!args))));
template not(alias pred)
Negates predicate pred.
import std.algorithm.searching : find;
import std.uni : isWhite;
string a = "   Hello, world!";
assert(find!(not!isWhite)(a) == "Hello, world!");
bool not(T...)(auto ref T args);
template pipe(fun...)
Composes passed-in functions fun[0], fun[1], ... returning a function f(x) that in turn returns ...(fun[1](fun[0](x))).... Each function can be a regular functions, a delegate, a lambda, or a string.
assert(pipe!("a + b", a => a * 10)(2, 3) == 50);
pipe can return by reference.
int a;
assert(&pipe!("a", "a")(a) == &a);
Template bloat reduction
enum  a = "a * 2";
alias b = e => e + 2;

alias p0 = pipe!(pipe!(a, b), pipe!(b, a));
alias p1 = pipe!(a, b, b, a);

static assert(__traits(isSame, p0, p1));
ref auto pipe(Args...)(auto ref Args args);
template aliasCall(string methodName, TemplateArgs...)
Replaces call operator (opCall) for the value using its method. The funciton is designed to use with topology  or topology .
methodName name of the methods to use for opCall and opIndex
TemplateArgs template arguments
static struct S
    auto lightConst()() const @property { return S(); }

    auto fun(size_t ct_param = 1)(size_t rt_param) const
        return rt_param + ct_param;

S s;

auto sfun = aliasCall!"fun"(s);
assert(sfun(3) == 4);

auto sfun10 = aliasCall!("fun", 10)(s);   // uses fun!10
assert(sfun10(3) == 13);
@property AliasCall!(T, methodName, TemplateArgs) aliasCall(T)(T value);

@property ref @trusted AliasCall!(T, methodName, TemplateArgs) aliasCall(T)(return ref T value);
T value the value to wrap
wrapped value with implemented opCall and opIndex methods
template recurseTemplatePipe(alias Template, size_t N, Args...)
// import mir.ndslice.topology: map;
alias map(alias fun) = a => a; // some template
static assert (__traits(isSame, recurseTemplatePipe!(map, 2, "a * 2"), map!(map!"a * 2")));
template selfAndRecurseTemplatePipe(alias Template, size_t N, Args...)
// import mir.ndslice.topology: map;
alias map(alias fun) = a => a; // some template
static assert (__traits(isSame, selfAndRecurseTemplatePipe!(map, 2, "a * 2"), map!(pipe!("a * 2", map!"a * 2"))));
template selfTemplatePipe(alias Template, size_t N, Args...)
// import mir.ndslice.topology: map;
alias map(alias fun) = a => a; // some template
static assert (__traits(isSame, selfTemplatePipe!(map, 2, "a * 2"), map!(pipe!("a * 2", map!"a * 2"))));