On this page
std.functional
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 std.algorithm
or std.range
.
Function Name | Description |
---|---|
adjoin |
Joins a couple of functions into one that executes the original functions independently and returns a tuple with all the results. |
compose , 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. |
forward |
Forwards function arguments while saving ref-ness. |
lessThan , greaterThan , equalTo |
Ready-made predicate functions to compare two values. |
memoize |
Creates a function that caches its result for fast re-evaluation. |
not |
Creates a function that negates another. |
partial |
Creates a function that binds the first argument of a given function to a given value. |
curry |
Converts a multi-argument function into a series of single-argument functions. f(x, y) == curry(f)(x)(y) |
reverseArgs |
Predicate that reverses the order of its arguments. |
toDelegate |
Converts a callable to a delegate. |
unaryFun , binaryFun |
Create a unary or binary function from a string. Most often used when defining algorithms on ranges. |
- License:
- Boost License 1.0.
- Authors:
- Andrei Alexandrescu
- Source
- std/functional.d
- template unaryFun(alias fun, string parmName = "a")
-
Transforms a
string
representing an expression into a unary function. Thestring
must either use symbol namea
as the parameter or provide the symbol via theparmName
argument.- Parameters:
-
fun a string
or a callableparmName the name of the parameter if fun
is a string. Defaults to"a"
.
- Returns:
-
If
fun
is astring
, a new single parameter function Iffun
is not astring
, an alias tofun
.
- Examples:
-
// Strings are compiled into functions: alias isEven = unaryFun!("(a & 1) == 0"); assert(isEven(2) && !isEven(1));
- template binaryFun(alias fun, string parm1Name = "a", string parm2Name = "b")
-
Transforms a
string
representing an expression into a binary function. Thestring
must either use symbol namesa
andb
as the parameters or provide the symbols via theparm1Name
andparm2Name
arguments.- Parameters:
-
fun a string
or a callableparm1Name the name of the first parameter if fun
is a string. Defaults to"a"
.parm2Name the name of the second parameter if fun
is a string. Defaults to"b"
.
- Returns:
-
If
fun
is not a string,binaryFun
aliases itself away tofun
.
- Examples:
-
alias less = binaryFun!("a < b"); assert(less(1, 2) && !less(2, 1)); alias greater = binaryFun!("a > b"); assert(!greater("1", "2") && greater("2", "1"));
- alias lessThan = safeOp!"<".safeOp(T0, T1)(auto ref T0 a, auto ref T1 b);
-
Predicate that returns a < b. Correctly compares signed and unsigned integers, ie. -1 < 2U.
- Examples:
-
assert(lessThan(2, 3)); assert(lessThan(2U, 3U)); assert(lessThan(2, 3.0)); assert(lessThan(-2, 3U)); assert(lessThan(2, 3U)); assert(!lessThan(3U, -2)); assert(!lessThan(3U, 2)); assert(!lessThan(0, 0)); assert(!lessThan(0U, 0)); assert(!lessThan(0, 0U));
- alias greaterThan = safeOp!">".safeOp(T0, T1)(auto ref T0 a, auto ref T1 b);
-
Predicate that returns a > b. Correctly compares signed and unsigned integers, ie. 2U > -1.
- Examples:
-
assert(!greaterThan(2, 3)); assert(!greaterThan(2U, 3U)); assert(!greaterThan(2, 3.0)); assert(!greaterThan(-2, 3U)); assert(!greaterThan(2, 3U)); assert(greaterThan(3U, -2)); assert(greaterThan(3U, 2)); assert(!greaterThan(0, 0)); assert(!greaterThan(0U, 0)); assert(!greaterThan(0, 0U));
- alias equalTo = safeOp!"==".safeOp(T0, T1)(auto ref T0 a, auto ref T1 b);
-
Predicate that returns a == b. Correctly compares signed and unsigned integers, ie. !(-1 == ~0U).
- Examples:
-
assert(equalTo(0U, 0)); assert(equalTo(0, 0U)); assert(!equalTo(-1, ~0U));
- template reverseArgs(alias pred)
-
N-ary predicate that reverses the order of arguments, e.g., given
pred(a, b, c)
, returnspred(c, b, a)
.- Parameters:
-
pred A callable
- Returns:
-
A function which calls
pred
after reversing the given parameters
- Examples:
-
alias gt = reverseArgs!(binaryFun!("a < b")); assert(gt(2, 1) && !gt(1, 1));
- Examples:
-
int x = 42; bool xyz(int a, int b) { return a * x < b / x; } auto foo = &xyz; foo(4, 5); alias zyx = reverseArgs!(foo); writeln(zyx(5, 4)); // foo(4, 5)
- Examples:
-
alias gt = reverseArgs!(binaryFun!("a < b")); assert(gt(2, 1) && !gt(1, 1)); int x = 42; bool xyz(int a, int b) { return a * x < b / x; } auto foo = &xyz; foo(4, 5); alias zyx = reverseArgs!(foo); writeln(zyx(5, 4)); // foo(4, 5)
- Examples:
-
int abc(int a, int b, int c) { return a * b + c; } alias cba = reverseArgs!abc; writeln(abc(91, 17, 32)); // cba(32, 17, 91)
- Examples:
-
int a(int a) { return a * 2; } alias _a = reverseArgs!a; writeln(a(2)); // _a(2)
- Examples:
-
int b() { return 4; } alias _b = reverseArgs!b; writeln(b()); // _b()
- template not(alias pred)
-
Negates predicate
pred
.- Parameters:
-
pred A string or a callable
- Returns:
-
A function which calls
pred
and returns the logical negation of its return value.
- Examples:
-
import std.algorithm.searching : find; import std.functional; import std.uni : isWhite; string a = " Hello, world!"; writeln(find!(not!isWhite)(a)); // "Hello, world!"
- template partial(alias fun, alias arg)
-
Partially applies fun by tying its first argument to arg.
- Parameters:
-
fun A callable arg The first argument to apply to fun
- Returns:
-
A new function which calls
fun
witharg
plus the passed parameters.
- Examples:
-
int fun(int a, int b) { return a + b; } alias fun5 = partial!(fun, 5); writeln(fun5(6)); // 11 // Note that in most cases you'd use an alias instead of a value // assignment. Using an alias allows you to partially evaluate template // functions without committing to a particular type of the function.
-
auto curry(alias F)()
Constraints: if (isCallable!F && Parameters!F.length);
auto curry(T)(T t)
Constraints: if (isCallable!T && Parameters!T.length); -
Takes a function of (potentially) many arguments, and returns a function taking one argument and returns a callable taking the rest. f(x, y) == curry(f)(x)(y)
- Parameters:
-
F a function taking at least one argument T t
a callable object whose opCall takes at least 1 object
- Returns:
- A single parameter callable object
- Examples:
-
int f(int x, int y, int z) { return x + y + z; } auto cf = curry!f; auto cf1 = cf(1); auto cf2 = cf(2); writeln(cf1(2)(3)); // f(1, 2, 3) writeln(cf2(2)(3)); // f(2, 2, 3)
- Examples:
-
//works with callable structs too struct S { int w; int opCall(int x, int y, int z) { return w + x + y + z; } } S s; s.w = 5; auto cs = curry(s); auto cs1 = cs(1); auto cs2 = cs(2); writeln(cs1(2)(3)); // s(1, 2, 3) writeln(cs1(2)(3)); // (1 + 2 + 3 + 5) writeln(cs2(2)(3)); // s(2, 2, 3)
-
template adjoin(F...) if (F.length == 1)
template adjoin(F...) if (F.length > 1) -
Takes multiple functions and adjoins them together.
- Parameters:
-
F the call-able(s) to adjoin
- Returns:
-
A new function which returns a
std.typecons.Tuple
. Each of the elements of the tuple will be the return values ofF
.
- 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]
).
- Examples:
-
import std.functional, std.typecons : Tuple; 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[0] == true && x[1] == 2);
- template compose(fun...) if (fun.length > 0)
-
Composes passed-in functions
fun[0], fun[1], ...
.- Parameters:
-
fun the call-able(s) or string
(s) to compose into one function
- Returns:
-
A new function
f(x)
that in turn returnsfun[0](fun[1](...(x)))...
.
- See Also:
-
pipe
- Examples:
-
import std.algorithm.comparison : equal; import std.algorithm.iteration : map; import std.array : split; import std.conv : to; // First split a string in whitespace-separated tokens and then // convert each token into an integer assert(compose!(map!(to!(int)), split)("1 2 3").equal([1, 2, 3]));
- template pipe(fun...)
-
Pipes functions in sequence. Offers the same functionality as
compose
, but with functions specified in reverse order. This may lead to more readable code in some situation because the order of execution is the same as lexical order.- Parameters:
-
fun the call-able(s) or string
(s) to compose into one function
- Returns:
-
A new function
f(x)
that in turn returnsfun[$-1](...fun[1](fun[0](x)))...
.
- Example
// Read an entire text file, split the resulting string in // whitespace-separated tokens, and then convert each token into an // integer int[] a = pipe!(readText, split, map!(to!(int)))("file.txt");
- See Also:
-
compose
- Examples:
-
import std.conv : to; string foo(int a) { return to!(string)(a); } int bar(string a) { return to!(int)(a) + 1; } double baz(int a) { return a + 0.5; } writeln(compose!(baz, bar, foo)(1)); // 2.5 writeln(pipe!(foo, bar, baz)(1)); // 2.5 writeln(compose!(baz, `to!(int)(a) + 1`, foo)(1)); // 2.5 writeln(compose!(baz, bar)("1"[])); // 2.5 writeln(compose!(baz, bar)("1")); // 2.5 writeln(compose!(`a + 0.5`, `to!(int)(a) + 1`, foo)(1)); // 2.5
-
ReturnType!fun memoize(alias fun)(Parameters!fun args);
ReturnType!fun memoize(alias fun, uint maxSize)(Parameters!fun args); -
Memoizes a function so as to avoid repeated computation. The memoization structure is a hash table keyed by a tuple of the function's arguments. There is a speed gain if the function is repeatedly called with the same arguments and is more expensive than a hash table lookup. For more information on memoization, refer to this book chapter.
- Example
double transmogrify(int a, string b) { ... expensive computation ... } alias fastTransmogrify = memoize!transmogrify; unittest { auto slow = transmogrify(2, "hello"); auto fast = fastTransmogrify(2, "hello"); assert(slow == fast); }
- Parameters:
-
fun the call-able to memozie maxSize The maximum size of the GC buffer to hold the return values
- Returns:
-
A new function which calls
fun
and caches its return values.
- Note
-
Technically the memoized function should be pure because
memoize
assumes it will always return the same result for a given tuple of arguments. However,memoize
does not enforce that because sometimes it is useful to memoize an impure function, too.
- Examples:
-
To memoize a recursive function, simply insert the memoized call in lieu of the plain recursive call. For example, to transform the exponential-time Fibonacci implementation into a linear-time computation:
ulong fib(ulong n) @safe nothrow { return n < 2 ? n : memoize!fib(n - 2) + memoize!fib(n - 1); } writeln(fib(10)); // 55
- Examples:
-
To improve the speed of the factorial function,
ulong fact(ulong n) @safe { return n < 2 ? 1 : n * memoize!fact(n - 1); } writeln(fact(10)); // 3628800
- Examples:
-
This memoizes all values of
fact
up to the largest argument. To only cache the final result, movememoize
outside the function as shown below.ulong factImpl(ulong n) @safe { return n < 2 ? 1 : n * factImpl(n - 1); } alias fact = memoize!factImpl; writeln(fact(10)); // 3628800
- Examples:
-
When the
maxSize
parameter is specified, memoize will used a fixed size hash table to limit the number of cached entries.ulong fact(ulong n) { // Memoize no more than 8 values return n < 2 ? 1 : n * memoize!(fact, 8)(n - 1); } writeln(fact(8)); // 40320 // using more entries than maxSize will overwrite existing entries writeln(fact(10)); // 3628800
-
auto toDelegate(F)(auto ref F fp)
Constraints: if (isCallable!F); -
Convert a callable to a delegate with the same parameter list and return type, avoiding heap allocations and use of auxiliary storage.
- Parameters:
-
F fp
a function pointer or an aggregate type with opCall
defined.
- Returns:
- A delegate with the context pointer pointing to nothing.
- Example
void doStuff() { writeln("Hello, world."); } void runDelegate(void delegate() myDelegate) { myDelegate(); } auto delegateToPass = toDelegate(&doStuff); runDelegate(delegateToPass); // Calls doStuff, prints "Hello, world."
- Bugs:
-
- Does not work with
@safe
functions. - Ignores C-style / D-style variadic arguments.
- Does not work with
- Examples:
-
static int inc(ref uint num) { num++; return 8675309; } uint myNum = 0; auto incMyNumDel = toDelegate(&inc); auto returnVal = incMyNumDel(myNum); writeln(myNum); // 1
- template forward(args...)
-
Forwards function arguments while keeping
out
,ref
, andlazy
on the parameters.- Parameters:
-
args a parameter list or an std.meta.AliasSeq
.
- Returns:
-
An
AliasSeq
ofargs
without
,ref
, andlazy
saved.
- Examples:
-
class C { static int foo(int n) { return 1; } static int foo(ref int n) { return 2; } } // with forward int bar()(auto ref int x) { return C.foo(forward!x); } // without forward int baz()(auto ref int x) { return C.foo(x); } int i; writeln(bar(1)); // 1 writeln(bar(i)); // 2 writeln(baz(1)); // 2 writeln(baz(i)); // 2
- Examples:
-
void foo(int n, ref string s) { s = null; foreach (i; 0 .. n) s ~= "Hello"; } // forwards all arguments which are bound to parameter tuple void bar(Args...)(auto ref Args args) { return foo(forward!args); } // forwards all arguments with swapping order void baz(Args...)(auto ref Args args) { return foo(forward!args[$/2..$], forward!args[0..$/2]); } string s; bar(1, s); writeln(s); // "Hello" baz(s, 2); writeln(s); // "HelloHello"
- Examples:
-
struct X { int i; this(this) { ++i; } } struct Y { private X x_; this()(auto ref X x) { x_ = forward!x; } } struct Z { private const X x_; this()(auto ref X x) { x_ = forward!x; } this()(auto const ref X x) { x_ = forward!x; } } X x; const X cx; auto constX = (){ const X x; return x; }; static assert(__traits(compiles, { Y y = x; })); static assert(__traits(compiles, { Y y = X(); })); static assert(!__traits(compiles, { Y y = cx; })); static assert(!__traits(compiles, { Y y = constX(); })); static assert(__traits(compiles, { Z z = x; })); static assert(__traits(compiles, { Z z = X(); })); static assert(__traits(compiles, { Z z = cx; })); static assert(__traits(compiles, { Z z = constX(); })); Y y1 = x; // ref lvalue, copy writeln(y1.x_.i); // 1 Y y2 = X(); // rvalue, move writeln(y2.x_.i); // 0 Z z1 = x; // ref lvalue, copy writeln(z1.x_.i); // 1 Z z2 = X(); // rvalue, move writeln(z2.x_.i); // 0 Z z3 = cx; // ref const lvalue, copy writeln(z3.x_.i); // 1 Z z4 = constX(); // const rvalue, copy writeln(z4.x_.i); // 1
© 1999–2021 The D Language Foundation
Licensed under the Boost License 1.0.
https://dlang.org/phobos/std_functional.html