Spec-Zone.ru › D

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
END_OF_DOCUMENT_MARKER
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.
Возвращает:
Экземпляр AliasSeq args с сохраненными 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API