std.functional
Функции, манипулирующие другими функциями.
Этот модуль предоставляет функции для композиции функций во время компиляции. Эти функции полезны при построении предикатов для алгоритмов в std.algorithm или std.range.
| Имя функции | Описание |
|---|---|
adjoin | Объединяет пару функций в одну, которая выполняет исходные функции независимо и возвращает кортеж со всеми результатами. |
compose, pipe
| Объединяет пару функций в одну, которая выполняет исходные функции по очереди, используя результат одной функции в качестве аргумента следующей функции. |
forward | Передает аргументы функции, сохраняя ссылочность. |
lessThan, greaterThan, equalTo
| Готовые предикатные функции для сравнения двух значений. |
memoize | Создаёт функцию, кэширующую свой результат для быстрого повторного вычисления. |
not | Создаёт функцию, инвертирующую другую. |
partial | Создаёт функцию, связывающую первый аргумент данной функции с заданным значением. |
curry | Преобразует функцию с несколькими аргументами в серию функций с одним аргументом. f(x, y) == curry(f)(x)(y) |
reverseArgs | Предикат, меняющий порядок своих аргументов. |
toDelegate | Преобразует вызываемый объект в делегат. |
unaryFun, binaryFun
| Создают функцию с одним или двумя аргументами из строки. Чаще всего используются при определении алгоритмов для диапазонов. |
- Лицензия:
- Лицензия Boost 1.0.
- Авторы:
- Andrei Alexandrescu
- Исходный код
- std/functional.d
- template unaryFun(alias fun, string parmName = "a")
-
Преобразует
string, представляющую выражение, в унарную функцию.stringдолжна либо использовать имя символаaв качестве параметра, либо предоставить символ с помощью аргументаparmName.- Параметры:
fun stringили вызываемый объектparmName имя параметра, если fun— строка. По умолчанию"a".
- Возвращает:
- Если
fun—string, новую однопараметровую функцию. Еслиfunнеstring, псевдоним дляfun.
- Примеры:
-
// 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")
-
Преобразует
string, представляющую выражение, в бинарную функцию.stringдолжна либо использовать имена символовaиbв качестве параметров, либо предоставить символы с помощью аргументовparm1Nameиparm2Name.- Параметры:
fun stringили вызываемый объектparm1Name имя первого параметра, если fun— строка. По умолчанию"a".parm2Name имя второго параметра, если fun— строка. По умолчанию"b".
- Возвращает:
- Если
funне строка,binaryFunсоздает псевдоним дляfun.
- Примеры:
-
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);
-
Предикат, возвращающий a < b. Правильно сравнивает целые числа со знаком и без знака, например, -1 < 2U.
- Примеры:
-
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);
-
Предикат, возвращающий a > b. Правильно сравнивает целые числа со знаком и без знака, например, 2U > -1.
- Примеры:
-
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);
-
Предикат, возвращающий a == b. Правильно сравнивает целые числа со знаком и без знака, например, !(-1 == ~0U).
- Примеры:
-
assert(equalTo(0U, 0)); assert(equalTo(0, 0U)); assert(!equalTo(-1, ~0U));
- template reverseArgs(alias pred)
-
N-арный предикат, меняющий порядок аргументов, например, для
pred(a, b, c), возвращаетpred(c, b, a).- Параметры:
pred Вызываемый объект
- Возвращает:
- Функцию, которая вызывает
predпосле изменения порядка параметров.
- Примеры:
-
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)
- Примеры:
-
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)
- Примеры:
-
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)
- Примеры:
-
int a(int a) { return a * 2; } alias _a = reverseArgs!a; writeln(a(2)); // _a(2)
- Примеры:
-
int b() { return 4; } alias _b = reverseArgs!b; writeln(b()); // _b()
- template not(alias pred)
-
Инвертирует предикат
pred.- Параметры:
pred Строка или вызываемый объект
- Возвращает:
- Функцию, которая вызывает
predи возвращает логическое отрицание её результата.
- Примеры:
-
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)
-
Применяет частично fun, связывая её первый аргумент с arg.
- Параметры:
fun Вызываемый объект arg Первый аргумент для применения к fun
- Возвращает:
- Новую функцию, которая вызывает
funсargи переданными параметрами.
- Примеры:
-
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); -
Принимает функцию (с потенциально множеством аргументов) и возвращает функцию, принимающую один аргумент и возвращающую вызываемый объект, принимающий остальные. f(x, y) == curry(f)(x)(y)
- Параметры:
F функция, принимающая как минимум один аргумент T tвызываемый объект, чья opCall принимает как минимум 1 объект
- Возвращает:
- Вызываемый объект с одним параметром
- Примеры:
-
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)
- Примеры:
-
//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) -
Объединяет несколько функций.
- Параметры:
F вызываемые объекты для объединения
- Возвращает:
- Новую функцию, которая возвращает
std.typecons.Tuple. Каждый элемент кортежа будет результатом вызоваF.
- Примечание
- В случае, когда предоставлена только одна функция (
F.length == 1), adjoin просто создает псевдоним для этой функции (F[0]).
- Примеры:
-
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)
-
Компонует переданные функции
fun[0], fun[1], ....- Параметры:
fun вызываемые объекты или stringдля компоновки в одну функцию
- Возвращает:
- Новую функцию
f(x), которая, в свою очередь, возвращаетfun[0](fun[1](...(x)))....
- См. также:
pipe
- Примеры:
-
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...)
-
Выполняет функции последовательно. Предлагает ту же функциональность, что и
compose, но с функциями, указанными в обратном порядке. Это может привести к более читаемому коду в некоторых ситуациях, поскольку порядок выполнения совпадает с лексическим порядком.- Параметры:
fun вызываемые объекты или stringдля компоновки в одну функцию
- Возвращает:
- Новую функцию
f(x), которая, в свою очередь, возвращаетfun[$-1](...fun[1](fun[0](x)))....
- Пример
// 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");- См. также:
compose
- Примеры:
-
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); -
Кэширует функцию, чтобы избежать повторных вычислений. Структура кэширования — хеш-таблица, ключи которой — кортежи аргументов функции. Выигрыш в производительности, если функция вызывается многократно с одними и теми же аргументами и является более ресурсоёмкой, чем поиск в хеш-таблице. Более подробную информацию о кэшировании см. в данной главе книги.
- Пример
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); }- Параметры:
fun вызываемый объект для кэширования maxSize Максимальный размер буфера сборки мусора для хранения возвращаемых значений
- Возвращает:
- Новую функцию, которая вызывает
funи кэширует её возвращаемые значения.
- Примечание
- Теоретически кэшируемая функция должна быть чистой, поскольку
memoizeпредполагает, что она всегда возвращает один и тот же результат для заданного набора аргументов. Однакоmemoizeне проверяет это, так как иногда полезно кэшировать и нечистые функции.
- Примеры:
- Для кэширования рекурсивной функции просто замените обычный рекурсивный вызов кэшируемым. Например, для преобразования вычисления чисел Фибоначчи с экспоненциальным временем в вычисления с линейным временем:
ulong fib(ulong n) @safe nothrow { return n < 2 ? n : memoize!fib(n - 2) + memoize!fib(n - 1); } writeln(fib(10)); // 55
- Примеры:
- Для повышения скорости функции факториала,
ulong fact(ulong n) @safe { return n < 2 ? 1 : n * memoize!fact(n - 1); } writeln(fact(10)); // 3628800
- Примеры:
- Этот код кэширует все значения
factдо самого большого аргумента. Для кэширования только конечного результата поместитеmemoizeза пределами функции, как показано ниже.ulong factImpl(ulong n) @safe { return n < 2 ? 1 : n * factImpl(n - 1); } alias fact = memoize!factImpl; writeln(fact(10)); // 3628800
- Примеры:
- При указании параметра
maxSize, memoize будет использовать хеш-таблицу фиксированного размера, чтобы ограничить количество кэшированных записей.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); -
Преобразует вызываемый объект в делегат с таким же списком параметров и типом возвращаемого значения, избегая выделения памяти и использования вспомогательного хранилища.
- Параметры:
F fpуказатель на функцию или агрегатное значение с определённым opCall.
- Возвращает:
- Делегат с указателем контекста, указывающим на ничто.
- Пример
void doStuff() { writeln("Hello, world."); } void runDelegate(void delegate() myDelegate) { myDelegate(); } auto delegateToPass = toDelegate(&doStuff); runDelegate(delegateToPass); // Calls doStuff, prints "Hello, world."- Ошибки:
- Не работает с
@safeфункциями. - Игнорирует аргументы с переменным числом параметров по C- или D-стилю.
- Не работает с
- Примеры:
-
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...)
-
Передает аргументы функции, сохраняя
out,ref, иlazyпараметров.- Параметры:
args список параметров или std.meta.AliasSeq.
- Возвращает:
- Экземпляр
AliasSeqargsс сохраненнымиout,ref, иlazy.
- Примеры:
-
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
- Примеры:
-
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"
- Примеры:
-
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