英語版
このページの英語版を見る

std.functional

他の関数を操作する関数。
このモジュールはコンパイル時の関数合成のための関数を提供する。これらの のアルゴリズムの述語を構成するときに役立つ。 std.algorithmまたは std.range.
"関数" 名称 説明
adjoin いくつかの関数をひとつに結合する。 関数を1つに結合する。
compose, pipe いくつかの関数を1つに結合する。 関数を1つに結合する。 関数の引数に使う。
lessThan, greaterThan, equalTo つの値を比較するための既製の述語関数。
memoize 高速な再評価のために結果をキャッシュする関数を作成する。
not 別の関数を否定する関数を作成する。
partial 与えられた関数の第1引数を与えられた値にバインドする関数を作成する。 を指定された値にバインドする関数を作成する。
curry 複数引数の関数を一連の単一引数の関数に変換する。 f(x, y) == curry(f)(x)(y).
reverseArgs 引数の順序を逆にする述語。
toDelegate callable関数をデリゲートに変換する。
unaryFun, binaryFun 文字列から単項または二項関数を作成する。最もよく使われる 範囲のアルゴリズムを定義するときに使用される。
bind 構造体のフィールドを関数の引数として渡す。
template unaryFun(alias fun, string parmName = "a")
string 、式を単項式に変換する。 関数に変換する。string は、シンボル名a をパラメータとして使用するか、 の引数でシンボルを指定しなければならない。 をパラメータとして使用するか、parmName 引数でシンボルを指定する。
Parameters:
fun string または callable
parmName fun が文字列の場合、パラメータ名。デフォルトは は"a" である。
Returns:
funstring の場合、新しい単一パラメータ関数" を返す。
funstring でない場合、fun へのエイリアスである。
Examples:
// 文字列は関数にコンパイルされる:
alias isEven = unaryFun!("(a & 1) == 0");
assert(isEven(2) && !isEven(1));
template binaryFun(alias fun, string parm1Name = "a", string parm2Name = "b")
string 、式をバイナリ関数に変換する。この関数は string は、シンボル名ab を引数として使うか、または parm1Nameparm2Name の引数でシンボルを指定する。
Parameters:
fun string または callable
parm1Name fun が文字列の場合、最初のパラメータ名。 デフォルトは"a" である。
parm2Name fun が文字列の場合、2 番目のパラメータ名。 デフォルトは"b"
Returns:
fun が文字列でない場合、 binaryFunにエイリアスする。 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);
a < bを返す述語。 符号付き整数と符号なし整数を正しく比較する。
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);
a > b を返す述語。 符号付き整数と符号なし整数を正しく比較する。
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);
a == b を返す述語。 符号付き整数と符号なし整数を正しく比較する。
Examples:
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) を返す。
Parameters:
pred 呼び出し可能な
Returns:
与えられたパラメータを反転させた後、pred を呼び出す関数。
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)
pred を否定する。
Parameters:
pred 文字列または callable
Returns:
pred 、その論理否定を返す。 を呼び出し、その戻り値の論理否定を返す関数。
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)
部分的に は、第1引数をargに結びつけることでfunを適用する。
Parameters:
fun 呼び出し可能な
arg に適用する最初の引数はfun
Returns:
arg に渡されたパラメータを加えて、fun を呼び出す新しい関数。
Examples:
int fun(int a, int b) { return a + b; }
alias fun5 = partial!(fun, 5);
writeln(fun5(6)); // 11
// ほとんどの場合、値の代入の代わりにエイリアスを使うことに注意してほしい。
// エイリアスを使うことで、関数の特定の型にこだわることなく、
// テンプレート化された関数を部分的に評価することができる。
Examples:
// オーバーロードは、部分的に適用された関数が
// 残りの引数で呼び出されたときに解決される。
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);
多くの引数を持つ(可能性のある)関数を受け取り、1つの引数を取る関数を返す。 f(x, y) == curry(f)(x)(y)
Parameters:
F 少なくとも1つの引数をとる関数。
T t opCallが少なくとも1つのオブジェクトを取る callable オブジェクト
Returns:
1つのパラメータを持つ呼び出し可能オブジェクト
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:
//呼び出し可能な構造体でも動作する
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)
複数の"関数"を取り込み、それらを隣接させる。
Parameters:
F 隣接させるcall-able(複数可)
Returns:
を返す新しい関数である。 std.typecons.Tuple.を返す新しい関数である。 F の戻り値となる。

注釈: 関数は1つしか提供されない。 単一の関数のみが提供される特殊なケースでは、以下のようになる。 (F.length == 1) の場合、アジョインは単に渡された関数のエイリアスになる。 (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)
引き渡された関数は、fun[0], fun[1], ...
Parameters:
fun call-able(s)またはstring(s)を1つの関数にまとめる。
Returns:
fun[0](fun[1](...(x)))... を返す新しい関数f(x)
See Also:
Examples:
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]));
template pipe(fun...)
関数を順番にパイプする。 compose と同じ機能を提供するが、関数は逆順に指定される。これは を逆順に指定する。 実行順序は()()順と同じである。
Parameters:
fun call-able(複数可)またはstring(複数可)を1つの関数にまとめる。
Returns:
fun[$-1](...fun[1](fun[0](x)))... を返す新しい関数f(x)

例:" を返す。

// テキストファイル全体を読み込み、
// 得られた文字列を空白で区切られたトークンで分割し、
// 各トークンを整数に変換する
int[] a = pipe!(readText, split, map!(to!(int)))("file.txt");

See Also:
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);
繰り返し計算を避けるために関数をメモする。 をメモ化する。メモ化の構造は、関数の引数のタプルをキーとするハッシュ・テーブルである。 関数の引数のタプルをキーとするハッシュ・テーブルである。関数が同じ引数で繰り返し呼び出され 関数は同じ引数で繰り返し呼び出され、ハッシュテーブルの検索よりも高価である。 ハッシュテーブルのルックアップよりも高価である。メモ化の詳細については、この本の章を参照のこと。

例:

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 memozieにコール可能な
maxSize 戻り値を保持するGCバッファの最大サイズ
Returns:
fun を呼び出し、その戻り値をキャッシュする新しい関数。

注釈:メモ化された関数は純粋でなければならない。 技術的には、メモ化された関数は純粋であるべきである。 memoizeなぜなら を想定しているからだ。しかし memoizeはそれを強制しない。 なぜなら、純粋でない関数をメモすることも時には有用だからである。

Examples:
再帰関数をメモ化するには、単純にプレーンな再帰呼び出しの代わりにメモ化された呼び出しを挿入する。 例えば、指数時間フィボナッチ実装を線形時間計算に変換する:
ulong fib(ulong n) @safe nothrow
{
    return n < 2 ? n : memoize!fib(n - 2) + memoize!fib(n - 1);
}
writeln(fib(10)); // 55
Examples:
階乗関数の速度を向上させる、
ulong fact(ulong n) @safe
{
    return n < 2 ? 1 : n * memoize!fact(n - 1);
}
writeln(fact(10)); // 3628800
Examples:
これは、最大の引数までのfact のすべての値をメモする。最終的な 結果をキャッシュするには memoizeを関数の外に移動させる。
ulong factImpl(ulong n) @safe
{
    return n < 2 ? 1 : n * factImpl(n - 1);
}
alias fact = memoize!factImpl;
writeln(fact(10)); // 3628800
Examples:
maxSize パラメーターが指定された場合、memoize は固定サイズのハッシュテーブルを使用し、キャッシュされるエントリーの数を制限する。 固定サイズのハッシュテーブルを使用する。
ulong fact(ulong n)
{
    // 8つ以下の値をメモする
    return n < 2 ? 1 : n * memoize!(fact, 8)(n - 1);
}
writeln(fact(8)); // 40320
// maxSize以上のエントリを使用すると、既存のエントリが上書きされる
writeln(fact(10)); // 3628800
auto toDelegate(F)(auto ref F fp)
if (isCallable!F);
callable を、同じパラメータ・リストと戻り値の型を持つ delegate に変換する。 ヒープ割り当てや補助記憶域の使用を避けることができる。
Parameters:
F fp opCall 、関数ポインタまたは集約型を定義する。
Returns:
コンテキスト・ポインタが何も指していないデリゲート。

例:

void doStuff() {
    writeln("Hello, world.");
}

void runDelegate(void delegate() myDelegate) {
    myDelegate();
}

auto delegateToPass = toDelegate(&doStuff);
runDelegate(delegateToPass);  // doStuffを呼び出し、"Hello, world."と表示する。

Bugs:
  • @safe 関数では動作しない。
  • C言語スタイル/D言語の可変長引数を無視する。
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)
構造体のフィールドを関数の引数として渡す。
構造体またはタプルのフィールドに一時的な名前を付けるために、関数リテラルとともに使用することができる。 タプルのフィールドに一時的な名前を付ける。
Parameters:
fun 構造体のフィールドが渡される callable。
Returns:
構造体を引数として受け取り、呼び出されたときにその構造体のフィールドを に渡す関数である。 fun フィールドを渡す関数である。
Examples:
タプル要素に名前をつける
import std.typecons : tuple;

auto name = tuple("John", "Doe");
string full = name.bind!((first, last) => first ~ " " ~ last);
writeln(full); // "John Doe"
Examples:
構造体フィールドを関数に渡す
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:
レンジパイプライン
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 フィールドが引数として使用される構造体またはタプル。
Returns:
fun(args.tupleof)