Menu

- Learn
- Documentation
  - Language Reference
  - Library Reference
  - Command-line Reference
  - Feature Overview
  - Articles
- Downloads
- Packages
- Community
  - Blog
  - Orgs using D
  - Twitter
  - Forums
  - IRC
  - Community Discord
  - Wiki
  - GitHub
  - Issues
  - Get involved
  - Contributors
  - Foundation
  - Security Team
  - Donate
  - Sponsors
- Resources
  - Tour
  - Books
  - Tutorials
  - Tools
  - Editors
  - IDEs
  - run.dlang.io
  - Visual D
  - Acknowledgments
  - D Style
  - Glossary
  - Sitemap

Search
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.
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. The string must either use symbol name a as the parameter or provide the symbol via the parmName argument.
  Parameters:

  fun | a string or a callable
  parmName | the name of the parameter if fun is a string. Defaults to "a".

  Returns:
  If fun is a string, a new single parameter function
  If fun is not a string, an alias to fun.
  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. The string must either use symbol names a and b as the parameters or provide the symbols via the parm1Name and parm2Name arguments.
  Parameters:

  fun | a string or a callable
  parm1Name | 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 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"));

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), returns pred(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.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 with arg 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.

  Examples:

      // Overloads are resolved when the partially applied function is called
      // with the remaining arguments.
      struct S
      {
          static char fun(int i, string s) { return s[i]; }
          static int fun(int a, int b) { return a * b; }
      }
      alias fun3 = partial!(S.fun, 3);
      writeln(fun3("hello")); // 'l'
      writeln(fun3(10)); // 30

auto `curry`(alias F)()
if (isCallable!F && Parameters!F.length);
auto `curry`(T)(T `t`)
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)
  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 of F.

  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.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 returns fun[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 returns fun[$-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, move `memoize` 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`)
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.
  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 `bind`(alias fun)
  Passes the fields of a struct as arguments to a function.
  Can be used with a function literal to give temporary names to the fields of a struct or tuple.
  Parameters:

  fun | Callable that the struct's fields will be passed to.

  Returns:
  A function that accepts a single struct as an argument and passes its fields to fun when called.
  Examples:
  Giving names to tuple elements

      import std.typecons : tuple;

      auto name = tuple("John", "Doe");
      string full = name.bind!((first, last) => first ~ " " ~ last);
      writeln(full); // "John Doe"

  Examples:
  Passing struct fields to a function

      import std.algorithm.comparison : min, max;

      struct Pair
      {
          int a;
          int b;
      }

      auto p = Pair(123, 456);
      assert(p.bind!min == 123); // min(p.a, p.b)
      assert(p.bind!max == 456); // max(p.a, p.b)

  Examples:
  In a range pipeline

      import std.algorithm.iteration : map, filter;
      import std.algorithm.comparison : equal;
      import std.typecons : tuple;

      auto ages = [
          tuple("Alice", 35),
          tuple("Bob",   64),
          tuple("Carol", 21),
          tuple("David", 39),
          tuple("Eve",   50)
      ];

      auto overForty = ages
          .filter!(bind!((name, age) => age > 40))
          .map!(bind!((name, age) => name));

      assert(overForty.equal(["Bob", "Eve"]));

  ref auto `bind`(T)(auto ref T `args`)
  if (is(T == struct));
    Parameters:

    T `args` | The struct or tuple whose fields will be used as arguments.

    Returns:
    fun(`args`.tupleof)

Copyright © 1999-2023 by the D Language Foundation | Page generated by Ddoc on Wed Mar 1 14:57:16 2023