Переместиться к: adjoin · binaryFun · binaryReverseArgs · compose · equalTo · forward · greaterThan · lessThan · memoize · not · partial · pipe · reverseArgs · toDelegate · unaryFun
Function Name | Description |
---|---|
adjoin | Объединяет несколько функций в одну, которая выполняет первоначальные функции независимо друг от друга, и возвращает кортеж со всеми результатами. |
compose, pipe | Соединяет несколько функций в одну, которая выполняет первоначальные функции, одну за другой, используя результат одной функции как аргумент в следующей функции. |
forward | Передаёт аргументы функции при сохранении ref-ности. |
lessThan, greaterThan, equalTo | Готовые функции-предикаты для сравнения двух величин. |
memoize | Создает функцию, которая кеширует свой результат для быстрого повторного вычисления. |
not | Создает функцию, которая отрицает другую. |
partial | Создает функцию, в которой первый аргумент данной функции привязан к данной величине. |
reverseArgs, binaryReverseArgs | Предикат, который инвертирует порядок своих аргументов. |
toDelegate | Преобразует вызываемый объект в делегат. |
unaryFun, binaryFun | Создаёт одноаргументную или двухаргументную функцию из строки. Чаще всего используется при определении алгоритмов на диапазонах. |
Исходный код: std/functional.d
unaryFun
(alias fun, string parmName = "a")unaryFun
сами приводятся к fun.// Строки компилируются в функции: alias isEven = unaryFun!("(a & 1) == 0"); assert(isEven(2) && !isEven(1));
binaryFun
(alias fun, string parm1Name = "a", string parm2Name = "b")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"));
lessThan
= safeOp!"<".safeOp(T0, T1)(auto ref T0 a, auto ref T1 b);
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));
greaterThan
= safeOp!">".safeOp(T0, T1)(auto ref T0 a, auto ref T1 b);
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));
equalTo
= safeOp!"==".safeOp(T0, T1)(auto ref T0 a, auto ref T1 b);
assert(equalTo(0U, 0)); assert(equalTo(0, 0U)); assert(!equalTo(-1, ~0U));
reverseArgs
(alias 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); assert(zyx(5, 4) == foo(4, 5));
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));
int a(int a) { return a * 2; } alias _a = reverseArgs!a; assert(a(2) == _a(2));
int b() { return 4; } alias _b = reverseArgs!b; assert(b() == _b());
binaryReverseArgs
(alias pred)alias gt = binaryReverseArgs!(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 = binaryReverseArgs!(foo); assert(zyx(5, 4) == foo(4, 5));
not
(alias pred)import std.algorithm.searching : find; import std.functional; import std.uni : isWhite; string a = " Hello, world!"; assert(find!(not!isWhite)(a) == "Hello, world!");
partial
(alias fun, alias arg)int fun(int a, int b) { return a + b; } alias fun5 = partial!(fun, 5); assert(fun5(6) == 11); // Заметьте, что в большинстве случаев вы будете использовать псевдоним // вместо назначаемой величины. Использование псевдонима позволяет вам // частично вычислить шаблон функции без привязки к конкретному типу функции.
adjoin
(F...) if (F.length == 1)adjoin
(F...) if (F.length > 1)Примечание:
В специальном случае, когда предоставлена только одна единственная функция
(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);
compose
(fun...)import std.algorithm.comparison : equal; import std.algorithm.iteration : map; import std.array : split; import std.conv : to; // Сначала разбить строку на разделенные пробелами лексемы, // а затем преобразовать каждую лексему в целое число assert(compose!(map!(to!(int)), split)("1 2 3").equal([1, 2, 3]));
pipe
(fun...)Пример:
// Прочитать весь текстовый файл, разделить результирующую строку // на разделённые пробелами лексемы, затем преобразовать // каждую лексему в целое int[] a = pipe!(readText, split, map!(to!(int)))("file.txt");
memoize
(alias fun)(Parameters!fun args
);
memoize
(alias fun, uint maxSize)(Parameters!fun args
);
Пример:
double transmogrify(int a, string b) { ... дорогое вычисление ... } alias fastTransmogrify = memoize!transmogrify; unittest { auto slow = transmogrify(2, "hello"); auto fast = fastTransmogrify(2, "hello"); assert(slow == fast); }Технически мемоизируемая функция должна быть чистой (pure), поскольку
memoize
предполагает, что она всегда возвращает одинаковый результат для данного кортежа аргументов. Тем не менее, memoize
не навязывает это, поскольку иногда бывает полезно мемоизировать также нечистую функцию.ulong fib(ulong n) @safe { return n < 2 ? n : memoize!fib(n - 2) + memoize!fib(n - 1); } assert(fib(10) == 55);
ulong fact(ulong n) @safe { return n < 2 ? 1 : n * memoize!fact(n - 1); } assert(fact(10) == 3628800);
memoize
за пределы функции, как показано ниже.
ulong factImpl(ulong n) @safe { return n < 2 ? 1 : n * factImpl(n - 1); } alias fact = memoize!factImpl; assert(fact(10) == 3628800);
memoize
будет использовать хэш-таблицу фиксированного размера, чтобы ограничить количество кешируемых данных.
ulong fact(ulong n) { // Мемоизировать не больше 8 значений return n < 2 ? 1 : n * memoize!(fact, 8)(n - 1); } assert(fact(8) == 40320); // использование большего количества данных, чем maxSize, перезапишет существующие данные assert(fact(10) == 3628800);
toDelegate
(F)(auto ref F fp
)Пример:
void doStuff() { writeln("Hello, world."); } void runDelegate(void delegate() myDelegate) { myDelegate(); } auto delegateToPass = toDelegate(&doStuff); runDelegate(delegateToPass); // Вызывает doStuff, печатает "Hello, world."
forward
(args...)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);
void foo(int n, ref string s) { s = null; foreach (i; 0..n) s ~= "Hello"; } // передает все аргументы, которые связаны с кортежем параметров void bar(Args...)(auto ref Args args) { return foo(forward!args); } // передает все аргументы с изменением порядка 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");