Report a bug
If you spot a problem with this page, click here to create a Bugzilla 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.
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-evalation. |
not | Creates a function that negates another. |
partial | Creates a function that binds the first argument of a given function to a given value. |
reverseArgs, binaryReverseArgs | 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:
Authors:
Source: std/functional.d
- Transforms a string representing an expression into a unary function. The string must either use symbol name a as the parameter or provide the symbol via the parmName argument. If fun is not a string, unaryFun aliases itself away to fun.Examples:
// Strings are compiled into functions: alias isEven = unaryFun!("(a & 1) == 0"); assert(isEven(2) && !isEven(1));
- Transforms a string representing an expression into a binary function. The string must either use symbol names a and b as the parameters or provide the symbols via the parm1Name and parm2Name arguments. If fun is not a string, binaryFun aliases itself away to fun.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"));
- 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));
- 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));
- 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));
- N-ary predicate that reverses the order of arguments, e.g., given pred(a, b, c), returns pred(c, b, a).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); assert(zyx(5, 4) == foo(4, 5));
Examples: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));
Examples:int a(int a) { return a * 2; } alias _a = reverseArgs!a; assert(a(2) == _a(2));
Examples:int b() { return 4; } alias _b = reverseArgs!b; assert(b() == _b());
- Binary predicate that reverses the order of arguments, e.g., given pred(a, b), returns pred(b, a).Examples:
alias gt = binaryReverseArgs!(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 = binaryReverseArgs!(foo); assert(zyx(5, 4) == foo(4, 5));
- Negates predicate pred.Examples:
import std.functional; import std.algorithm : find; import std.uni : isWhite; string a = " Hello, world!"; assert(find!(not!isWhite)(a) == "Hello, world!");
-
Examples:
int fun(int a, int b) { return a + b; } alias fun5 = partial!(fun, 5); assert(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.
- Takes multiple functions and adjoins them together. The result is a std.typecons.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]).
Examples:import std.functional, std.typecons; 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);
- Composes passed-in functions fun[0], fun[1], ... returning a function f(x) that in turn returns fun[0](fun[1](...(x))).... Each function can be a regular functions, a delegate, or a string.Examples:
import std.algorithm: equal, 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]));
- 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.
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");
- 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); }
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) { return n < 2 ? 1 : memoize!fib(n - 2) + memoize!fib(n - 1); } assert(fib(10) == 89);
Examples:To improve the speed of the factorial function,ulong fact(ulong n) { return n < 2 ? 1 : n * memoize!fact(n - 1); } assert(fact(10) == 3628800);
Examples: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); } assert(fact(8) == 40320); // using more entries than maxSize will overwrite existing entries assert(fact(10) == 3628800);
- Convert a callable to a delegate with the same parameter list and return type, avoiding heap allocations and use of auxiliary storage.
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.
- Forwards function arguments with saving ref-ness.Examples:
class C { static int foo(int n) { return 1; } static int foo(ref int n) { return 2; } } int bar()(auto ref int x) { return C.foo(forward!x); } assert(bar(1) == 1); int i; assert(bar(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); assert(s == "Hello"); baz(s, 2); assert(s == "HelloHello");
Copyright Andrei Alexandrescu 2008 - 2009.
| Page generated by
Ddoc on (no date time)