xref: /netbsd-src/external/gpl3/gcc/dist/libphobos/src/std/functional.d (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 // Written in the D programming language.
2 
3 /**
4 Functions that manipulate other functions.
5 
6 This module provides functions for compile time function composition. These
7 functions are helpful when constructing predicates for the algorithms in
8 $(MREF std, algorithm) or $(MREF std, range).
9 
10 $(SCRIPT inhibitQuickIndex = 1;)
11 $(DIVC quickindex,
12 $(BOOKTABLE ,
13 $(TR $(TH Function Name) $(TH Description)
14 )
15     $(TR $(TD $(LREF adjoin))
16         $(TD Joins a couple of functions into one that executes the original
17         functions independently and returns a tuple with all the results.
18     ))
19     $(TR $(TD $(LREF compose), $(LREF pipe))
20         $(TD Join a couple of functions into one that executes the original
21         functions one after the other, using one function's result for the next
22         function's argument.
23     ))
24     $(TR $(TD $(LREF lessThan), $(LREF greaterThan), $(LREF equalTo))
25         $(TD Ready-made predicate functions to compare two values.
26     ))
27     $(TR $(TD $(LREF memoize))
28         $(TD Creates a function that caches its result for fast re-evaluation.
29     ))
30     $(TR $(TD $(LREF not))
31         $(TD Creates a function that negates another.
32     ))
33     $(TR $(TD $(LREF partial))
34         $(TD Creates a function that binds the first argument of a given function
35         to a given value.
36     ))
37     $(TR $(TD $(LREF curry))
38         $(TD Converts a multi-argument function into a series of single-argument
39         functions.  f(x, y) == curry(f)(x)(y)
40     ))
41     $(TR $(TD $(LREF reverseArgs))
42         $(TD Predicate that reverses the order of its arguments.
43     ))
44     $(TR $(TD $(LREF toDelegate))
45         $(TD Converts a callable to a delegate.
46     ))
47     $(TR $(TD $(LREF unaryFun), $(LREF binaryFun))
48         $(TD Create a unary or binary function from a string. Most often
49         used when defining algorithms on ranges.
50     ))
51 ))
52 
53 Copyright: Copyright Andrei Alexandrescu 2008 - 2009.
54 License:   $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
55 Authors:   $(HTTP erdani.org, Andrei Alexandrescu)
56 Source:    $(PHOBOSSRC std/functional.d)
57 */
58 /*
59          Copyright Andrei Alexandrescu 2008 - 2009.
60 Distributed under the Boost Software License, Version 1.0.
61    (See accompanying file LICENSE_1_0.txt or copy at
62          http://www.boost.org/LICENSE_1_0.txt)
63 */
64 module std.functional;
65 
66 import std.meta : AliasSeq, Reverse;
67 import std.traits : isCallable, Parameters;
68 import std.conv : toCtString;
69 
70 import std.internal.attributes : betterC;
71 
72 public import core.lifetime : forward;
73 
needOpCallAlias(alias fun)74 private template needOpCallAlias(alias fun)
75 {
76     /* Determine whether or not unaryFun and binaryFun need to alias to fun or
77      * fun.opCall. Basically, fun is a function object if fun(...) compiles. We
78      * want is(unaryFun!fun) (resp., is(binaryFun!fun)) to be true if fun is
79      * any function object. There are 4 possible cases:
80      *
81      *  1) fun is the type of a function object with static opCall;
82      *  2) fun is an instance of a function object with static opCall;
83      *  3) fun is the type of a function object with non-static opCall;
84      *  4) fun is an instance of a function object with non-static opCall.
85      *
86      * In case (1), is(unaryFun!fun) should compile, but does not if unaryFun
87      * aliases itself to fun, because typeof(fun) is an error when fun itself
88      * is a type. So it must be aliased to fun.opCall instead. All other cases
89      * should be aliased to fun directly.
90      */
91     static if (is(typeof(fun.opCall) == function))
92     {
93         enum needOpCallAlias = !is(typeof(fun)) && __traits(compiles, () {
94             return fun(Parameters!fun.init);
95         });
96     }
97     else
98         enum needOpCallAlias = false;
99 }
100 
101 /**
102 Transforms a `string` representing an expression into a unary
103 function. The `string` must either use symbol name `a` as
104 the parameter or provide the symbol via the `parmName` argument.
105 
106 Params:
107     fun = a `string` or a callable
108     parmName = the name of the parameter if `fun` is a string. Defaults
109     to `"a"`.
110 Returns:
111     If `fun` is a `string`, a new single parameter function
112 
113     If `fun` is not a `string`, an alias to `fun`.
114 */
115 template unaryFun(alias fun, string parmName = "a")
116 {
117     static if (is(typeof(fun) : string))
118     {
119         static if (!fun._ctfeMatchUnary(parmName))
120         {
121             import std.algorithm, std.conv, std.exception, std.math, std.range, std.string;
122             import std.meta, std.traits, std.typecons;
123         }
unaryFun(ElementType)124         auto unaryFun(ElementType)(auto ref ElementType __a)
125         {
126             mixin("alias " ~ parmName ~ " = __a ;");
127             return mixin(fun);
128         }
129     }
130     else static if (needOpCallAlias!fun)
131     {
132         // https://issues.dlang.org/show_bug.cgi?id=9906
133         alias unaryFun = fun.opCall;
134     }
135     else
136     {
137         alias unaryFun = fun;
138     }
139 }
140 
141 ///
142 @safe unittest
143 {
144     // Strings are compiled into functions:
145     alias isEven = unaryFun!("(a & 1) == 0");
146     assert(isEven(2) && !isEven(1));
147 }
148 
149 @safe unittest
150 {
f1(int a)151     static int f1(int a) { return a + 1; }
152     static assert(is(typeof(unaryFun!(f1)(1)) == int));
153     assert(unaryFun!(f1)(41) == 42);
f2(int a)154     int f2(int a) { return a + 1; }
155     static assert(is(typeof(unaryFun!(f2)(1)) == int));
156     assert(unaryFun!(f2)(41) == 42);
157     assert(unaryFun!("a + 1")(41) == 42);
158     //assert(unaryFun!("return a + 1;")(41) == 42);
159 
160     int num = 41;
161     assert(unaryFun!"a + 1"(num) == 42);
162 
163     // https://issues.dlang.org/show_bug.cgi?id=9906
164     struct Seen
165     {
opCallSeen166         static bool opCall(int n) { return true; }
167     }
168     static assert(needOpCallAlias!Seen);
169     static assert(is(typeof(unaryFun!Seen(1))));
170     assert(unaryFun!Seen(1));
171 
172     Seen s;
173     static assert(!needOpCallAlias!s);
174     static assert(is(typeof(unaryFun!s(1))));
175     assert(unaryFun!s(1));
176 
177     struct FuncObj
178     {
opCallFuncObj179         bool opCall(int n) { return true; }
180     }
181     FuncObj fo;
182     static assert(!needOpCallAlias!fo);
183     static assert(is(typeof(unaryFun!fo)));
184     assert(unaryFun!fo(1));
185 
186     // Function object with non-static opCall can only be called with an
187     // instance, not with merely the type.
188     static assert(!is(typeof(unaryFun!FuncObj)));
189 }
190 
191 /**
192 Transforms a `string` representing an expression into a binary function. The
193 `string` must either use symbol names `a` and `b` as the parameters or
194 provide the symbols via the `parm1Name` and `parm2Name` arguments.
195 
196 Params:
197     fun = a `string` or a callable
198     parm1Name = the name of the first parameter if `fun` is a string.
199     Defaults to `"a"`.
200     parm2Name = the name of the second parameter if `fun` is a string.
201     Defaults to `"b"`.
202 Returns:
203     If `fun` is not a string, `binaryFun` aliases itself away to
204     `fun`.
205 */
206 template binaryFun(alias fun, string parm1Name = "a",
207         string parm2Name = "b")
208 {
209     static if (is(typeof(fun) : string))
210     {
211         static if (!fun._ctfeMatchBinary(parm1Name, parm2Name))
212         {
213             import std.algorithm, std.conv, std.exception, std.math, std.range, std.string;
214             import std.meta, std.traits, std.typecons;
215         }
binaryFun(ElementType1,ElementType2)216         auto binaryFun(ElementType1, ElementType2)
217             (auto ref ElementType1 __a, auto ref ElementType2 __b)
218         {
219             mixin("alias "~parm1Name~" = __a ;");
220             mixin("alias "~parm2Name~" = __b ;");
221             return mixin(fun);
222         }
223     }
224     else static if (needOpCallAlias!fun)
225     {
226         // https://issues.dlang.org/show_bug.cgi?id=9906
227         alias binaryFun = fun.opCall;
228     }
229     else
230     {
231         alias binaryFun = fun;
232     }
233 }
234 
235 ///
236 @safe unittest
237 {
238     alias less = binaryFun!("a < b");
239     assert(less(1, 2) && !less(2, 1));
240     alias greater = binaryFun!("a > b");
241     assert(!greater("1", "2") && greater("2", "1"));
242 }
243 
244 @safe unittest
245 {
f1(int a,string b)246     static int f1(int a, string b) { return a + 1; }
247     static assert(is(typeof(binaryFun!(f1)(1, "2")) == int));
248     assert(binaryFun!(f1)(41, "a") == 42);
f2(int a,string b)249     string f2(int a, string b) { return b ~ "2"; }
250     static assert(is(typeof(binaryFun!(f2)(1, "1")) == string));
251     assert(binaryFun!(f2)(1, "4") == "42");
252     assert(binaryFun!("a + b")(41, 1) == 42);
253     //@@BUG
254     //assert(binaryFun!("return a + b;")(41, 1) == 42);
255 
256     // https://issues.dlang.org/show_bug.cgi?id=9906
257     struct Seen
258     {
opCallSeen259         static bool opCall(int x, int y) { return true; }
260     }
261     static assert(is(typeof(binaryFun!Seen)));
262     assert(binaryFun!Seen(1,1));
263 
264     struct FuncObj
265     {
opCallFuncObj266         bool opCall(int x, int y) { return true; }
267     }
268     FuncObj fo;
269     static assert(!needOpCallAlias!fo);
270     static assert(is(typeof(binaryFun!fo)));
271     assert(unaryFun!fo(1,1));
272 
273     // Function object with non-static opCall can only be called with an
274     // instance, not with merely the type.
275     static assert(!is(typeof(binaryFun!FuncObj)));
276 }
277 
278 // skip all ASCII chars except a .. z, A .. Z, 0 .. 9, '_' and '.'.
_ctfeSkipOp(ref string op)279 private uint _ctfeSkipOp(ref string op)
280 {
281     if (!__ctfe) assert(false);
282     import std.ascii : isASCII, isAlphaNum;
283     immutable oldLength = op.length;
284     while (op.length)
285     {
286         immutable front = op[0];
287         if (front.isASCII() && !(front.isAlphaNum() || front == '_' || front == '.'))
288             op = op[1..$];
289         else
290             break;
291     }
292     return oldLength != op.length;
293 }
294 
295 // skip all digits
_ctfeSkipInteger(ref string op)296 private uint _ctfeSkipInteger(ref string op)
297 {
298     if (!__ctfe) assert(false);
299     import std.ascii : isDigit;
300     immutable oldLength = op.length;
301     while (op.length)
302     {
303         immutable front = op[0];
304         if (front.isDigit())
305             op = op[1..$];
306         else
307             break;
308     }
309     return oldLength != op.length;
310 }
311 
312 // skip name
_ctfeSkipName(ref string op,string name)313 private uint _ctfeSkipName(ref string op, string name)
314 {
315     if (!__ctfe) assert(false);
316     if (op.length >= name.length && op[0 .. name.length] == name)
317     {
318         op = op[name.length..$];
319         return 1;
320     }
321     return 0;
322 }
323 
324 // returns 1 if `fun` is trivial unary function
_ctfeMatchUnary(string fun,string name)325 private uint _ctfeMatchUnary(string fun, string name)
326 {
327     if (!__ctfe) assert(false);
328     fun._ctfeSkipOp();
329     for (;;)
330     {
331         immutable h = fun._ctfeSkipName(name) + fun._ctfeSkipInteger();
332         if (h == 0)
333         {
334             fun._ctfeSkipOp();
335             break;
336         }
337         else if (h == 1)
338         {
339             if (!fun._ctfeSkipOp())
340                 break;
341         }
342         else
343             return 0;
344     }
345     return fun.length == 0;
346 }
347 
348 @safe unittest
349 {
350     static assert(!_ctfeMatchUnary("sqrt(ё)", "ё"));
351     static assert(!_ctfeMatchUnary("ё.sqrt", "ё"));
352     static assert(!_ctfeMatchUnary(".ё+ё", "ё"));
353     static assert(!_ctfeMatchUnary("_ё+ё", "ё"));
354     static assert(!_ctfeMatchUnary("ёё", "ё"));
355     static assert(_ctfeMatchUnary("a+a", "a"));
356     static assert(_ctfeMatchUnary("a + 10", "a"));
357     static assert(_ctfeMatchUnary("4 == a", "a"));
358     static assert(_ctfeMatchUnary("2 == a", "a"));
359     static assert(_ctfeMatchUnary("1 != a", "a"));
360     static assert(_ctfeMatchUnary("a != 4", "a"));
361     static assert(_ctfeMatchUnary("a< 1", "a"));
362     static assert(_ctfeMatchUnary("434 < a", "a"));
363     static assert(_ctfeMatchUnary("132 > a", "a"));
364     static assert(_ctfeMatchUnary("123 >a", "a"));
365     static assert(_ctfeMatchUnary("a>82", "a"));
366     static assert(_ctfeMatchUnary("ё>82", "ё"));
367     static assert(_ctfeMatchUnary("ё[ё(ё)]", "ё"));
368     static assert(_ctfeMatchUnary("ё[21]", "ё"));
369 }
370 
371 // returns 1 if `fun` is trivial binary function
_ctfeMatchBinary(string fun,string name1,string name2)372 private uint _ctfeMatchBinary(string fun, string name1, string name2)
373 {
374     if (!__ctfe) assert(false);
375     fun._ctfeSkipOp();
376     for (;;)
377     {
378         immutable h = fun._ctfeSkipName(name1) + fun._ctfeSkipName(name2) + fun._ctfeSkipInteger();
379         if (h == 0)
380         {
381             fun._ctfeSkipOp();
382             break;
383         }
384         else if (h == 1)
385         {
386             if (!fun._ctfeSkipOp())
387                 break;
388         }
389         else
390             return 0;
391     }
392     return fun.length == 0;
393 }
394 
395 @safe unittest
396 {
397 
398     static assert(!_ctfeMatchBinary("sqrt(ё)", "ё", "b"));
399     static assert(!_ctfeMatchBinary("ё.sqrt", "ё", "b"));
400     static assert(!_ctfeMatchBinary(".ё+ё", "ё", "b"));
401     static assert(!_ctfeMatchBinary("_ё+ё", "ё", "b"));
402     static assert(!_ctfeMatchBinary("ёё", "ё", "b"));
403     static assert(_ctfeMatchBinary("a+a", "a", "b"));
404     static assert(_ctfeMatchBinary("a + 10", "a", "b"));
405     static assert(_ctfeMatchBinary("4 == a", "a", "b"));
406     static assert(_ctfeMatchBinary("2 == a", "a", "b"));
407     static assert(_ctfeMatchBinary("1 != a", "a", "b"));
408     static assert(_ctfeMatchBinary("a != 4", "a", "b"));
409     static assert(_ctfeMatchBinary("a< 1", "a", "b"));
410     static assert(_ctfeMatchBinary("434 < a", "a", "b"));
411     static assert(_ctfeMatchBinary("132 > a", "a", "b"));
412     static assert(_ctfeMatchBinary("123 >a", "a", "b"));
413     static assert(_ctfeMatchBinary("a>82", "a", "b"));
414     static assert(_ctfeMatchBinary("ё>82", "ё", "q"));
415     static assert(_ctfeMatchBinary("ё[ё(10)]", "ё", "q"));
416     static assert(_ctfeMatchBinary("ё[21]", "ё", "q"));
417 
418     static assert(!_ctfeMatchBinary("sqrt(ё)+b", "b", "ё"));
419     static assert(!_ctfeMatchBinary("ё.sqrt-b", "b", "ё"));
420     static assert(!_ctfeMatchBinary(".ё+b", "b", "ё"));
421     static assert(!_ctfeMatchBinary("_b+ё", "b", "ё"));
422     static assert(!_ctfeMatchBinary("ba", "b", "a"));
423     static assert(_ctfeMatchBinary("a+b", "b", "a"));
424     static assert(_ctfeMatchBinary("a + b", "b", "a"));
425     static assert(_ctfeMatchBinary("b == a", "b", "a"));
426     static assert(_ctfeMatchBinary("b == a", "b", "a"));
427     static assert(_ctfeMatchBinary("b != a", "b", "a"));
428     static assert(_ctfeMatchBinary("a != b", "b", "a"));
429     static assert(_ctfeMatchBinary("a< b", "b", "a"));
430     static assert(_ctfeMatchBinary("b < a", "b", "a"));
431     static assert(_ctfeMatchBinary("b > a", "b", "a"));
432     static assert(_ctfeMatchBinary("b >a", "b", "a"));
433     static assert(_ctfeMatchBinary("a>b", "b", "a"));
434     static assert(_ctfeMatchBinary("ё>b", "b", "ё"));
435     static assert(_ctfeMatchBinary("b[ё(-1)]", "b", "ё"));
436     static assert(_ctfeMatchBinary("ё[-21]", "b", "ё"));
437 }
438 
439 //undocumented
440 template safeOp(string S)
441 if (S=="<"||S==">"||S=="<="||S==">="||S=="=="||S=="!=")
442 {
443     import std.traits : isIntegral;
444     private bool unsafeOp(ElementType1, ElementType2)(ElementType1 a, ElementType2 b) pure
445         if (isIntegral!ElementType1 && isIntegral!ElementType2)
446     {
447         import std.traits : CommonType;
448         alias T = CommonType!(ElementType1, ElementType2);
449         return mixin("cast(T)a "~S~" cast(T) b");
450     }
451 
safeOp(T0,T1)452     bool safeOp(T0, T1)(auto ref T0 a, auto ref T1 b)
453     {
454         import std.traits : mostNegative;
455         static if (isIntegral!T0 && isIntegral!T1 &&
456                    (mostNegative!T0 < 0) != (mostNegative!T1 < 0))
457         {
458             static if (S == "<=" || S == "<")
459             {
460                 static if (mostNegative!T0 < 0)
461                     immutable result = a < 0 || unsafeOp(a, b);
462                 else
463                     immutable result = b >= 0 && unsafeOp(a, b);
464             }
465             else
466             {
467                 static if (mostNegative!T0 < 0)
468                     immutable result = a >= 0 && unsafeOp(a, b);
469                 else
470                     immutable result = b < 0 || unsafeOp(a, b);
471             }
472         }
473         else
474         {
475             static assert(is(typeof(mixin("a "~S~" b"))),
476                 "Invalid arguments: Cannot compare types " ~ T0.stringof ~ " and " ~ T1.stringof ~ ".");
477 
478             immutable result = mixin("a "~S~" b");
479         }
480         return result;
481     }
482 }
483 
484 @safe unittest //check user defined types
485 {
486     import std.algorithm.comparison : equal;
487     struct Foo
488     {
489         int a;
opEqualsFoo490         auto opEquals(Foo foo)
491         {
492             return a == foo.a;
493         }
494     }
495     assert(safeOp!"!="(Foo(1), Foo(2)));
496 }
497 
498 /**
499    Predicate that returns $(D_PARAM a < b).
500    Correctly compares signed and unsigned integers, ie. -1 < 2U.
501 */
502 alias lessThan = safeOp!"<";
503 
504 ///
505 pure @safe @nogc nothrow unittest
506 {
507     assert(lessThan(2, 3));
508     assert(lessThan(2U, 3U));
509     assert(lessThan(2, 3.0));
510     assert(lessThan(-2, 3U));
511     assert(lessThan(2, 3U));
512     assert(!lessThan(3U, -2));
513     assert(!lessThan(3U, 2));
514     assert(!lessThan(0, 0));
515     assert(!lessThan(0U, 0));
516     assert(!lessThan(0, 0U));
517 }
518 
519 /**
520    Predicate that returns $(D_PARAM a > b).
521    Correctly compares signed and unsigned integers, ie. 2U > -1.
522 */
523 alias greaterThan = safeOp!">";
524 
525 ///
526 @safe unittest
527 {
528     assert(!greaterThan(2, 3));
529     assert(!greaterThan(2U, 3U));
530     assert(!greaterThan(2, 3.0));
531     assert(!greaterThan(-2, 3U));
532     assert(!greaterThan(2, 3U));
533     assert(greaterThan(3U, -2));
534     assert(greaterThan(3U, 2));
535     assert(!greaterThan(0, 0));
536     assert(!greaterThan(0U, 0));
537     assert(!greaterThan(0, 0U));
538 }
539 
540 /**
541    Predicate that returns $(D_PARAM a == b).
542    Correctly compares signed and unsigned integers, ie. !(-1 == ~0U).
543 */
544 alias equalTo = safeOp!"==";
545 
546 ///
547 @safe unittest
548 {
549     assert(equalTo(0U, 0));
550     assert(equalTo(0, 0U));
551     assert(!equalTo(-1, ~0U));
552 }
553 /**
554 N-ary predicate that reverses the order of arguments, e.g., given
555 $(D pred(a, b, c)), returns $(D pred(c, b, a)).
556 
557 Params:
558     pred = A callable
559 Returns:
560     A function which calls `pred` after reversing the given parameters
561 */
reverseArgs(alias pred)562 template reverseArgs(alias pred)
563 {
564     auto reverseArgs(Args...)(auto ref Args args)
565     if (is(typeof(pred(Reverse!args))))
566     {
567         return pred(Reverse!args);
568     }
569 }
570 
571 ///
572 @safe unittest
573 {
574     alias gt = reverseArgs!(binaryFun!("a < b"));
575     assert(gt(2, 1) && !gt(1, 1));
576 }
577 
578 ///
579 @safe unittest
580 {
581     int x = 42;
xyz(int a,int b)582     bool xyz(int a, int b) { return a * x < b / x; }
583     auto foo = &xyz;
584     foo(4, 5);
585     alias zyx = reverseArgs!(foo);
586     assert(zyx(5, 4) == foo(4, 5));
587 }
588 
589 ///
590 @safe unittest
591 {
592     alias gt = reverseArgs!(binaryFun!("a < b"));
593     assert(gt(2, 1) && !gt(1, 1));
594     int x = 42;
xyz(int a,int b)595     bool xyz(int a, int b) { return a * x < b / x; }
596     auto foo = &xyz;
597     foo(4, 5);
598     alias zyx = reverseArgs!(foo);
599     assert(zyx(5, 4) == foo(4, 5));
600 }
601 
602 ///
603 @safe unittest
604 {
abc(int a,int b,int c)605     int abc(int a, int b, int c) { return a * b + c; }
606     alias cba = reverseArgs!abc;
607     assert(abc(91, 17, 32) == cba(32, 17, 91));
608 }
609 
610 ///
611 @safe unittest
612 {
a(int a)613     int a(int a) { return a * 2; }
614     alias _a = reverseArgs!a;
615     assert(a(2) == _a(2));
616 }
617 
618 ///
619 @safe unittest
620 {
b()621     int b() { return 4; }
622     alias _b = reverseArgs!b;
623     assert(b() == _b());
624 }
625 
626 /**
627 Negates predicate `pred`.
628 
629 Params:
630     pred = A string or a callable
631 Returns:
632     A function which calls `pred` and returns the logical negation of its
633     return value.
634  */
not(alias pred)635 template not(alias pred)
636 {
637     auto not(T...)(auto ref T args)
638     {
639         static if (is(typeof(!pred(args))))
640             return !pred(args);
641         else static if (T.length == 1)
642             return !unaryFun!pred(args);
643         else static if (T.length == 2)
644             return !binaryFun!pred(args);
645         else
646             static assert(0);
647     }
648 }
649 
650 ///
651 @safe unittest
652 {
653     import std.algorithm.searching : find;
654     import std.uni : isWhite;
655     string a = "   Hello, world!";
656     assert(find!(not!isWhite)(a) == "Hello, world!");
657 }
658 
659 @safe unittest
660 {
661     assert(not!"a != 5"(5));
662     assert(not!"a != b"(5, 5));
663 
664     assert(not!(() => false)());
665     assert(not!(a => a != 5)(5));
666     assert(not!((a, b) => a != b)(5, 5));
667     assert(not!((a, b, c) => a * b * c != 125 )(5, 5, 5));
668 }
669 
670 /**
671 $(LINK2 http://en.wikipedia.org/wiki/Partial_application, Partially
672 applies) $(D_PARAM fun) by tying its first argument to $(D_PARAM arg).
673 
674 Params:
675     fun = A callable
676     arg = The first argument to apply to `fun`
677 Returns:
678     A new function which calls `fun` with `arg` plus the passed parameters.
679  */
partial(alias fun,alias arg)680 template partial(alias fun, alias arg)
681 {
682     import std.traits : isCallable;
683     // Check whether fun is a user defined type which implements opCall or a template.
684     // As opCall itself can be templated, std.traits.isCallable does not work here.
685     enum isSomeFunctor = (is(typeof(fun) == struct) || is(typeof(fun) == class)) && __traits(hasMember, fun, "opCall");
686     static if (isSomeFunctor || __traits(isTemplate, fun))
687     {
688         auto partial(Ts...)(Ts args2)
689         {
690             static if (is(typeof(fun(arg, args2))))
691             {
692                 return fun(arg, args2);
693             }
694             else
695             {
696                 static string errormsg()
697                 {
698                     string msg = "Cannot call '" ~ fun.stringof ~ "' with arguments " ~
699                         "(" ~ arg.stringof;
700                     foreach (T; Ts)
701                         msg ~= ", " ~ T.stringof;
702                     msg ~= ").";
703                     return msg;
704                 }
705                 static assert(0, errormsg());
706             }
707         }
708     }
709     else static if (!isCallable!fun)
710     {
711         static assert(false, "Cannot apply partial to a non-callable '" ~ fun.stringof ~ "'.");
712     }
713     else
714     {
715         import std.meta : Filter;
716 
717         static if (__traits(compiles, __traits(getOverloads,
718             __traits(parent, fun), __traits(identifier, fun))))
719             alias overloads = __traits(getOverloads, __traits(parent, fun),
720                 __traits(identifier, fun));
721         else
722             alias overloads = AliasSeq!(fun);
723 
724         enum isCallableWithArg(alias fun) = Parameters!fun.length > 0 &&
725             is(typeof(arg) : Parameters!fun[0]);
726         alias candidates = Filter!(isCallableWithArg, overloads);
727 
728         static if (overloads.length == 1 && Parameters!fun.length == 0)
729         {
730             static assert(0, "Cannot partially apply '" ~ fun.stringof ~ "'." ~
731                 "'" ~ fun.stringof ~ "' has 0 arguments.");
732         }
733         else static if (candidates.length == 0)
734         {
735             import std.meta : NoDuplicates, staticMap;
736 
737             enum hasParameters(alias fun) = Parameters!fun.length > 0;
738             alias firstParameter(alias fun) = Parameters!fun[0];
739             alias firstParameters = NoDuplicates!(
740                 staticMap!(firstParameter, Filter!(hasParameters, overloads)));
741 
742             string errorMsg()
743             {
744                 string msg = "Argument mismatch for '" ~ fun.stringof ~
745                     "': expected " ~ firstParameters[0].stringof;
746                 static foreach (firstParam; firstParameters[1 .. $])
747                     msg ~= " or " ~ firstParam.stringof;
748                 msg ~= ", but got " ~ typeof(arg).stringof ~ ".";
749 
750                 return msg;
751             }
752             static assert(0, errorMsg());
753         }
754         else
755         {
756             import std.traits : ReturnType;
757             static foreach (candidate; candidates)
758                 ReturnType!candidate partial(Parameters!candidate[1..$] args2)
759                 {
760                     return candidate(arg, args2);
761                 }
762         }
763     }
764 }
765 
766 ///
767 @safe unittest
768 {
fun(int a,int b)769     int fun(int a, int b) { return a + b; }
770     alias fun5 = partial!(fun, 5);
771     assert(fun5(6) == 11);
772     // Note that in most cases you'd use an alias instead of a value
773     // assignment. Using an alias allows you to partially evaluate template
774     // functions without committing to a particular type of the function.
775 }
776 
777 // https://issues.dlang.org/show_bug.cgi?id=21457
778 ///
779 @safe unittest
780 {
781     // Overloads are resolved when the partially applied function is called
782     // with the remaining arguments.
783     struct S
784     {
funS785         static char fun(int i, string s) { return s[i]; }
funS786         static int fun(int a, int b) { return a * b; }
787     }
788     alias fun3 = partial!(S.fun, 3);
789     assert(fun3("hello") == 'l');
790     assert(fun3(10) == 30);
791 }
792 
793 // tests for partially evaluating callables
794 @safe unittest
795 {
f1(int a,int b)796     static int f1(int a, int b) { return a + b; }
797     assert(partial!(f1, 5)(6) == 11);
798 
f2(int a,int b)799     int f2(int a, int b) { return a + b; }
800     int x = 5;
801     assert(partial!(f2, x)(6) == 11);
802     x = 7;
803     assert(partial!(f2, x)(6) == 13);
804     static assert(partial!(f2, 5)(6) == 11);
805 
806     auto dg = &f2;
807     auto f3 = &partial!(dg, x);
808     assert(f3(6) == 13);
809 
funOneArg(int a)810     static int funOneArg(int a) { return a; }
811     assert(partial!(funOneArg, 1)() == 1);
812 
funThreeArgs(int a,int b,int c)813     static int funThreeArgs(int a, int b, int c) { return a + b + c; }
814     alias funThreeArgs1 = partial!(funThreeArgs, 1);
815     assert(funThreeArgs1(2, 3) == 6);
816     static assert(!is(typeof(funThreeArgs1(2))));
817 
818     enum xe = 5;
819     alias fe = partial!(f2, xe);
820     static assert(fe(6) == 11);
821 }
822 
823 // tests for partially evaluating templated/overloaded callables
824 @safe unittest
825 {
add(A,B)826     static auto add(A, B)(A x, B y)
827     {
828         return x + y;
829     }
830 
831     alias add5 = partial!(add, 5);
832     assert(add5(6) == 11);
833     static assert(!is(typeof(add5())));
834     static assert(!is(typeof(add5(6, 7))));
835 
836     // taking address of templated partial evaluation needs explicit type
837     auto dg = &add5!(int);
838     assert(dg(6) == 11);
839 
840     int x = 5;
841     alias addX = partial!(add, x);
842     assert(addX(6) == 11);
843 
844     static struct Callable
845     {
opCallCallable846         static string opCall(string a, string b) { return a ~ b; }
opCallCallable847         int opCall(int a, int b) { return a * b; }
opCallCallable848         double opCall(double a, double b) { return a + b; }
849     }
850     Callable callable;
851     assert(partial!(Callable, "5")("6") == "56");
852     assert(partial!(callable, 5)(6) == 30);
853     assert(partial!(callable, 7.0)(3.0) == 7.0 + 3.0);
854 
855     static struct TCallable
856     {
opCallTCallable857         auto opCall(A, B)(A a, B b)
858         {
859             return a + b;
860         }
861     }
862     TCallable tcallable;
863     assert(partial!(tcallable, 5)(6) == 11);
864     static assert(!is(typeof(partial!(tcallable, "5")(6))));
865 
866     static struct NonCallable{}
867     static assert(!__traits(compiles, partial!(NonCallable, 5)), "Partial should not work on non-callable structs.");
868     static assert(!__traits(compiles, partial!(NonCallable.init, 5)),
869         "Partial should not work on instances of non-callable structs.");
870 
funOneArg(A)871     static A funOneArg(A)(A a) { return a; }
872     alias funOneArg1 = partial!(funOneArg, 1);
873     assert(funOneArg1() == 1);
874 
funThreeArgs(A,B,C)875     static auto funThreeArgs(A, B, C)(A a, B b, C c) { return a + b + c; }
876     alias funThreeArgs1 = partial!(funThreeArgs, 1);
877     assert(funThreeArgs1(2, 3) == 6);
878     static assert(!is(typeof(funThreeArgs1(1))));
879 
880     auto dg2 = &funOneArg1!();
881     assert(dg2() == 1);
882 }
883 
884 // Fix https://issues.dlang.org/show_bug.cgi?id=15732
885 @safe unittest
886 {
887     // Test whether it works with functions.
partialFunction()888     auto partialFunction(){
889         auto fullFunction = (float a, float b, float c) => a + b / c;
890         alias apply1 = partial!(fullFunction, 1);
891         return &apply1;
892     }
893     auto result = partialFunction()(2, 4);
894     assert(result == 1.5f);
895 
896     // And with delegates.
partialDelegate(float c)897     auto partialDelegate(float c){
898         auto fullDelegate = (float a, float b) => a + b / c;
899         alias apply1 = partial!(fullDelegate, 1);
900         return &apply1;
901     }
902     auto result2 = partialDelegate(4)(2);
903     assert(result2 == 1.5f);
904 }
905 
906 /**
907 Takes a function of (potentially) many arguments, and returns a function taking
908 one argument and returns a callable taking the rest.  f(x, y) == curry(f)(x)(y)
909 
910 Params:
911     F = a function taking at least one argument
912     t = a callable object whose opCall takes at least 1 object
913 Returns:
914     A single parameter callable object
915 */
916 template curry(alias F)
917 if (isCallable!F && Parameters!F.length)
918 {
919     //inspired from the implementation from Artur Skawina here:
920     //https://forum.dlang.org/post/mailman.1626.1340110492.24740.digitalmars-d@puremagic.com
921     //This implementation stores a copy of all filled in arguments with each curried result
922     //this way, the curried functions are independent and don't share any references
923     //eg: auto fc = curry!f;  auto fc1 = fc(1); auto fc2 = fc(2); fc1(3) != fc2(3)
CurryImpl(size_t N)924     struct CurryImpl(size_t N)
925     {
926         alias FParams = Parameters!F;
927         FParams[0 .. N] storedArguments;
928         static if (N > 0)
929         {
930             this(U : FParams[N - 1])(ref CurryImpl!(N - 1) prev, ref U arg)
931             {
932                 storedArguments[0 .. N - 1] = prev.storedArguments[];
933                 storedArguments[N-1] = arg;
934             }
935         }
936 
937         auto opCall(U : FParams[N])(auto ref U arg) return scope
938         {
939             static if (N == FParams.length - 1)
940             {
941                 return F(storedArguments, arg);
942             }
943             else
944             {
945                 return CurryImpl!(N + 1)(this, arg);
946             }
947         }
948     }
949 
950     auto curry()
951     {
952         CurryImpl!0 res;
953         return res; // return CurryImpl!0.init segfaults for delegates on Windows
954     }
955 }
956 
957 ///
958 pure @safe @nogc nothrow unittest
959 {
960     int f(int x, int y, int z)
961     {
962         return x + y + z;
963     }
964     auto cf = curry!f;
965     auto cf1 = cf(1);
966     auto cf2 = cf(2);
967 
968     assert(cf1(2)(3) == f(1, 2, 3));
969     assert(cf2(2)(3) == f(2, 2, 3));
970 }
971 
972 ///ditto
973 auto curry(T)(T t)
974 if (isCallable!T && Parameters!T.length)
975 {
976     static auto fun(ref T inst, ref Parameters!T args)
977     {
978         return inst(args);
979     }
980 
981     return curry!fun()(t);
982 }
983 
984 ///
985 pure @safe @nogc nothrow unittest
986 {
987     //works with callable structs too
988     struct S
989     {
990         int w;
991         int opCall(int x, int y, int z)
992         {
993             return w + x + y + z;
994         }
995     }
996 
997     S s;
998     s.w = 5;
999 
1000     auto cs = curry(s);
1001     auto cs1 = cs(1);
1002     auto cs2 = cs(2);
1003 
1004     assert(cs1(2)(3) == s(1, 2, 3));
1005     assert(cs1(2)(3) == (1 + 2 + 3 + 5));
1006     assert(cs2(2)(3) ==s(2, 2, 3));
1007 }
1008 
1009 
1010 @safe pure @nogc nothrow unittest
1011 {
1012     //currying a single argument function does nothing
1013     int pork(int a){ return a*2;}
1014     auto curryPork = curry!pork;
1015     assert(curryPork(0) == pork(0));
1016     assert(curryPork(1) == pork(1));
1017     assert(curryPork(-1) == pork(-1));
1018     assert(curryPork(1000) == pork(1000));
1019 
1020     //test 2 argument function
1021     double mixedVeggies(double a, int b, bool)
1022     {
1023         return a + b;
1024     }
1025 
1026     auto mixedCurry = curry!mixedVeggies;
1027     assert(mixedCurry(10)(20)(false) == mixedVeggies(10, 20, false));
1028     assert(mixedCurry(100)(200)(true) == mixedVeggies(100, 200, true));
1029 
1030     // struct with opCall
1031     struct S
1032     {
1033         double opCall(int x, double y, short z) const pure nothrow @nogc
1034         {
1035             return x*y*z;
1036         }
1037     }
1038 
1039     S s;
1040     auto curriedStruct = curry(s);
1041     assert(curriedStruct(1)(2)(short(3)) == s(1, 2, short(3)));
1042     assert(curriedStruct(300)(20)(short(10)) == s(300, 20, short(10)));
1043 }
1044 
1045 pure @safe nothrow unittest
1046 {
1047     auto cfl = curry!((double a, int b)  => a + b);
1048     assert(cfl(13)(2) == 15);
1049 
1050     int c = 42;
1051     auto cdg = curry!((double a, int b)  => a + b + c);
1052     assert(cdg(13)(2) == 57);
1053 
1054     static class C
1055     {
1056         int opCall(int mult, int add) pure @safe nothrow @nogc scope
1057         {
1058             return  mult * 42 + add;
1059         }
1060     }
1061 
1062     scope C ci = new C();
1063     scope cc = curry(ci);
1064     assert(cc(2)(4) == ci(2, 4));
1065 }
1066 
1067 // Disallows callables without parameters
1068 pure @safe @nogc nothrow unittest
1069 {
1070     static void noargs() {}
1071     static assert(!__traits(compiles, curry!noargs()));
1072 
1073     static struct NoArgs
1074     {
1075         void opCall() {}
1076     }
1077 
1078     static assert(!__traits(compiles, curry(NoArgs.init)));
1079 }
1080 
1081 private template Iota(size_t n)
1082 {
1083     static if (n == 0)
1084         alias Iota = AliasSeq!();
1085     else
1086         alias Iota = AliasSeq!(Iota!(n - 1), n - 1);
1087 }
1088 
1089 /**
1090 Takes multiple functions and adjoins them together.
1091 
1092 Params:
1093     F = the call-able(s) to adjoin
1094 Returns:
1095     A new function which returns a $(REF Tuple, std,typecons). Each of the
1096     elements of the tuple will be the return values of `F`.
1097 
1098 Note: In the special case where only a single function is provided
1099 ($(D F.length == 1)), adjoin simply aliases to the single passed function
1100 (`F[0]`).
1101 */
1102 template adjoin(F...)
1103 if (F.length >= 1)
1104 {
1105     static if (F.length == 1)
1106         alias adjoin = F[0];
1107     else
1108         auto adjoin(V...)(auto ref V a)
1109         {
1110             import std.typecons : tuple;
1111             import std.meta : staticMap;
1112 
1113             auto resultElement(size_t i)()
1114             {
1115                 return F[i](a);
1116             }
1117 
1118             return tuple(staticMap!(resultElement, Iota!(F.length)));
1119         }
1120 }
1121 
1122 ///
1123 @safe unittest
1124 {
1125     import std.typecons : Tuple;
1126     static bool f1(int a) { return a != 0; }
1127     static int f2(int a) { return a / 2; }
1128     auto x = adjoin!(f1, f2)(5);
1129     assert(is(typeof(x) == Tuple!(bool, int)));
1130     assert(x[0] == true && x[1] == 2);
1131 }
1132 
1133 @safe unittest
1134 {
1135     import std.typecons : Tuple;
1136     static bool F1(int a) { return a != 0; }
1137     auto x1 = adjoin!(F1)(5);
1138     static int F2(int a) { return a / 2; }
1139     auto x2 = adjoin!(F1, F2)(5);
1140     assert(is(typeof(x2) == Tuple!(bool, int)));
1141     assert(x2[0] && x2[1] == 2);
1142     auto x3 = adjoin!(F1, F2, F2)(5);
1143     assert(is(typeof(x3) == Tuple!(bool, int, int)));
1144     assert(x3[0] && x3[1] == 2 && x3[2] == 2);
1145 
1146     bool F4(int a) { return a != x1; }
1147     alias eff4 = adjoin!(F4);
1148     static struct S
1149     {
1150         bool delegate(int) @safe store;
1151         int fun() { return 42 + store(5); }
1152     }
1153     S s;
1154     s.store = (int a) { return eff4(a); };
1155     auto x4 = s.fun();
1156     assert(x4 == 43);
1157 }
1158 
1159 @safe unittest
1160 {
1161     import std.meta : staticMap;
1162     import std.typecons : Tuple, tuple;
1163     alias funs = staticMap!(unaryFun, "a", "a * 2", "a * 3", "a * a", "-a");
1164     alias afun = adjoin!funs;
1165     assert(afun(5) == tuple(5, 10, 15, 25, -5));
1166 
1167     static class C{}
1168     alias IC = immutable(C);
1169     IC foo(){return typeof(return).init;}
1170     Tuple!(IC, IC, IC, IC) ret1 = adjoin!(foo, foo, foo, foo)();
1171 
1172     static struct S{int* p;}
1173     alias IS = immutable(S);
1174     IS bar(){return typeof(return).init;}
1175     enum Tuple!(IS, IS, IS, IS) ret2 = adjoin!(bar, bar, bar, bar)();
1176 }
1177 
1178 // https://issues.dlang.org/show_bug.cgi?id=21347
1179 @safe @betterC unittest
1180 {
1181     alias f = (int n) => n + 1;
1182     alias g = (int n) => n + 2;
1183     alias h = (int n) => n + 3;
1184     alias i = (int n) => n + 4;
1185 
1186     auto result = adjoin!(f, g, h, i)(0);
1187 
1188     assert(result[0] == 1);
1189     assert(result[1] == 2);
1190     assert(result[2] == 3);
1191     assert(result[3] == 4);
1192 }
1193 
1194 /**
1195    Composes passed-in functions $(D fun[0], fun[1], ...).
1196 
1197    Params:
1198         fun = the call-able(s) or `string`(s) to compose into one function
1199     Returns:
1200         A new function `f(x)` that in turn returns `fun[0](fun[1](...(x)))...`.
1201 
1202    See_Also: $(LREF pipe)
1203 */
1204 template compose(fun...)
1205 if (fun.length > 0)
1206 {
1207     static if (fun.length == 1)
1208     {
1209         alias compose = unaryFun!(fun[0]);
1210     }
1211     else
1212     {
1213         alias fun0 = unaryFun!(fun[0]);
1214         alias rest = compose!(fun[1 .. $]);
1215 
1216         auto compose(Args...)(Args args)
1217         {
1218             return fun0(rest(args));
1219         }
1220     }
1221 }
1222 
1223 ///
1224 @safe unittest
1225 {
1226     import std.algorithm.comparison : equal;
1227     import std.algorithm.iteration : map;
1228     import std.array : split;
1229     import std.conv : to;
1230 
1231     // First split a string in whitespace-separated tokens and then
1232     // convert each token into an integer
1233     assert(compose!(map!(to!(int)), split)("1 2 3").equal([1, 2, 3]));
1234 }
1235 
1236 // https://issues.dlang.org/show_bug.cgi?id=6484
1237 @safe unittest
1238 {
1239     int f(int a) { return a; }
1240     int g(int a) { return a; }
1241     int h(int a,int b,int c) { return a * b * c; }
1242 
1243     alias F = compose!(f,g,h);
1244     assert(F(1,2,3) == f(g(h(1,2,3))));
1245 }
1246 
1247 /**
1248    Pipes functions in sequence. Offers the same functionality as $(D
1249    compose), but with functions specified in reverse order. This may
1250    lead to more readable code in some situation because the order of
1251    execution is the same as lexical order.
1252 
1253    Params:
1254         fun = the call-able(s) or `string`(s) to compose into one function
1255     Returns:
1256         A new function `f(x)` that in turn returns `fun[$-1](...fun[1](fun[0](x)))...`.
1257 
1258    Example:
1259 
1260 ----
1261 // Read an entire text file, split the resulting string in
1262 // whitespace-separated tokens, and then convert each token into an
1263 // integer
1264 int[] a = pipe!(readText, split, map!(to!(int)))("file.txt");
1265 ----
1266 
1267    See_Also: $(LREF compose)
1268  */
1269 alias pipe(fun...) = compose!(Reverse!(fun));
1270 
1271 ///
1272 @safe unittest
1273 {
1274     import std.conv : to;
1275     string foo(int a) { return to!(string)(a); }
1276     int bar(string a) { return to!(int)(a) + 1; }
1277     double baz(int a) { return a + 0.5; }
1278     assert(compose!(baz, bar, foo)(1) == 2.5);
1279     assert(pipe!(foo, bar, baz)(1) == 2.5);
1280 
1281     assert(compose!(baz, `to!(int)(a) + 1`, foo)(1) == 2.5);
1282     assert(compose!(baz, bar)("1"[]) == 2.5);
1283 
1284     assert(compose!(baz, bar)("1") == 2.5);
1285 
1286     assert(compose!(`a + 0.5`, `to!(int)(a) + 1`, foo)(1) == 2.5);
1287 }
1288 
1289 /**
1290  * $(LINK2 https://en.wikipedia.org/wiki/Memoization, Memoizes) a function so as
1291  * to avoid repeated computation. The memoization structure is a hash table keyed by a
1292  * tuple of the function's arguments. There is a speed gain if the
1293  * function is repeatedly called with the same arguments and is more
1294  * expensive than a hash table lookup. For more information on memoization, refer to $(HTTP docs.google.com/viewer?url=http%3A%2F%2Fhop.perl.plover.com%2Fbook%2Fpdf%2F03CachingAndMemoization.pdf, this book chapter).
1295 
1296 Example:
1297 ----
1298 double transmogrify(int a, string b)
1299 {
1300    ... expensive computation ...
1301 }
1302 alias fastTransmogrify = memoize!transmogrify;
1303 unittest
1304 {
1305     auto slow = transmogrify(2, "hello");
1306     auto fast = fastTransmogrify(2, "hello");
1307     assert(slow == fast);
1308 }
1309 ----
1310 
1311 Params:
1312     fun = the call-able to memozie
1313     maxSize = The maximum size of the GC buffer to hold the return values
1314 Returns:
1315     A new function which calls `fun` and caches its return values.
1316 
1317 Note:
1318     Technically the memoized function should be pure because `memoize` assumes it will
1319     always return the same result for a given tuple of arguments. However, `memoize` does not
1320     enforce that because sometimes it is useful to memoize an impure function, too.
1321 */
1322 template memoize(alias fun)
1323 {
1324     import std.traits : ReturnType;
1325      // https://issues.dlang.org/show_bug.cgi?id=13580
1326     // alias Args = Parameters!fun;
1327 
1328     ReturnType!fun memoize(Parameters!fun args)
1329     {
1330         alias Args = Parameters!fun;
1331         import std.typecons : Tuple;
1332         import std.traits : Unqual;
1333 
1334         static Unqual!(ReturnType!fun)[Tuple!Args] memo;
1335         auto t = Tuple!Args(args);
1336         if (auto p = t in memo)
1337             return *p;
1338         auto r = fun(args);
1339         memo[t] = r;
1340         return r;
1341     }
1342 }
1343 
1344 /// ditto
1345 template memoize(alias fun, uint maxSize)
1346 {
1347     import std.traits : ReturnType;
1348      // https://issues.dlang.org/show_bug.cgi?id=13580
1349     // alias Args = Parameters!fun;
1350     ReturnType!fun memoize(Parameters!fun args)
1351     {
1352         import std.meta : staticMap;
1353         import std.traits : hasIndirections, Unqual;
1354         import std.typecons : tuple;
1355         static struct Value { staticMap!(Unqual, Parameters!fun) args; Unqual!(ReturnType!fun) res; }
1356         static Value[] memo;
1357         static size_t[] initialized;
1358 
1359         if (!memo.length)
1360         {
1361             import core.memory : GC;
1362 
1363             // Ensure no allocation overflows
1364             static assert(maxSize < size_t.max / Value.sizeof);
1365             static assert(maxSize < size_t.max - (8 * size_t.sizeof - 1));
1366 
1367             enum attr = GC.BlkAttr.NO_INTERIOR | (hasIndirections!Value ? 0 : GC.BlkAttr.NO_SCAN);
1368             memo = (cast(Value*) GC.malloc(Value.sizeof * maxSize, attr))[0 .. maxSize];
1369             enum nwords = (maxSize + 8 * size_t.sizeof - 1) / (8 * size_t.sizeof);
1370             initialized = (cast(size_t*) GC.calloc(nwords * size_t.sizeof, attr | GC.BlkAttr.NO_SCAN))[0 .. nwords];
1371         }
1372 
1373         import core.bitop : bt, bts;
1374         import core.lifetime : emplace;
1375 
1376         size_t hash;
1377         foreach (ref arg; args)
1378             hash = hashOf(arg, hash);
1379         // cuckoo hashing
1380         immutable idx1 = hash % maxSize;
1381         if (!bt(initialized.ptr, idx1))
1382         {
1383             emplace(&memo[idx1], args, fun(args));
1384             // only set to initialized after setting args and value
1385             // https://issues.dlang.org/show_bug.cgi?id=14025
1386             bts(initialized.ptr, idx1);
1387             return memo[idx1].res;
1388         }
1389         else if (memo[idx1].args == args)
1390             return memo[idx1].res;
1391         // FNV prime
1392         immutable idx2 = (hash * 16_777_619) % maxSize;
1393         if (!bt(initialized.ptr, idx2))
1394         {
1395             emplace(&memo[idx2], memo[idx1]);
1396             bts(initialized.ptr, idx2);
1397         }
1398         else if (memo[idx2].args == args)
1399             return memo[idx2].res;
1400         else if (idx1 != idx2)
1401             memo[idx2] = memo[idx1];
1402 
1403         memo[idx1] = Value(args, fun(args));
1404         return memo[idx1].res;
1405     }
1406 }
1407 
1408 /**
1409  * To _memoize a recursive function, simply insert the memoized call in lieu of the plain recursive call.
1410  * For example, to transform the exponential-time Fibonacci implementation into a linear-time computation:
1411  */
1412 @safe nothrow
1413 unittest
1414 {
1415     ulong fib(ulong n) @safe nothrow
1416     {
1417         return n < 2 ? n : memoize!fib(n - 2) + memoize!fib(n - 1);
1418     }
1419     assert(fib(10) == 55);
1420 }
1421 
1422 /**
1423  * To improve the speed of the factorial function,
1424  */
1425 @safe unittest
1426 {
1427     ulong fact(ulong n) @safe
1428     {
1429         return n < 2 ? 1 : n * memoize!fact(n - 1);
1430     }
1431     assert(fact(10) == 3628800);
1432 }
1433 
1434 /**
1435  * This memoizes all values of `fact` up to the largest argument. To only cache the final
1436  * result, move `memoize` outside the function as shown below.
1437  */
1438 @safe unittest
1439 {
1440     ulong factImpl(ulong n) @safe
1441     {
1442         return n < 2 ? 1 : n * factImpl(n - 1);
1443     }
1444     alias fact = memoize!factImpl;
1445     assert(fact(10) == 3628800);
1446 }
1447 
1448 /**
1449  * When the `maxSize` parameter is specified, memoize will used
1450  * a fixed size hash table to limit the number of cached entries.
1451  */
1452 @system unittest // not @safe due to memoize
1453 {
1454     ulong fact(ulong n)
1455     {
1456         // Memoize no more than 8 values
1457         return n < 2 ? 1 : n * memoize!(fact, 8)(n - 1);
1458     }
1459     assert(fact(8) == 40320);
1460     // using more entries than maxSize will overwrite existing entries
1461     assert(fact(10) == 3628800);
1462 }
1463 
1464 @system unittest // not @safe due to memoize
1465 {
1466     import core.math : sqrt;
1467     alias msqrt = memoize!(function double(double x) { return sqrt(x); });
1468     auto y = msqrt(2.0);
1469     assert(y == msqrt(2.0));
1470     y = msqrt(4.0);
1471     assert(y == sqrt(4.0));
1472 
1473     // alias mrgb2cmyk = memoize!rgb2cmyk;
1474     // auto z = mrgb2cmyk([43, 56, 76]);
1475     // assert(z == mrgb2cmyk([43, 56, 76]));
1476 
1477     //alias mfib = memoize!fib;
1478 
1479     static ulong fib(ulong n) @safe
1480     {
1481         alias mfib = memoize!fib;
1482         return n < 2 ? 1 : mfib(n - 2) + mfib(n - 1);
1483     }
1484 
1485     auto z = fib(10);
1486     assert(z == 89);
1487 
1488     static ulong fact(ulong n) @safe
1489     {
1490         alias mfact = memoize!fact;
1491         return n < 2 ? 1 : n * mfact(n - 1);
1492     }
1493     assert(fact(10) == 3628800);
1494 
1495     // https://issues.dlang.org/show_bug.cgi?id=12568
1496     static uint len2(const string s) { // Error
1497     alias mLen2 = memoize!len2;
1498     if (s.length == 0)
1499         return 0;
1500     else
1501         return 1 + mLen2(s[1 .. $]);
1502     }
1503 
1504     int _func(int x) @safe { return 1; }
1505     alias func = memoize!(_func, 10);
1506     assert(func(int.init) == 1);
1507     assert(func(int.init) == 1);
1508 }
1509 
1510 // https://issues.dlang.org/show_bug.cgi?id=16079
1511 // memoize should work with arrays
1512 @system unittest // not @safe with -dip1000 due to memoize
1513 {
1514     int executed = 0;
1515     T median(T)(const T[] nums) {
1516         import std.algorithm.sorting : sort;
1517         executed++;
1518         auto arr = nums.dup;
1519         arr.sort();
1520         if (arr.length % 2)
1521             return arr[$ / 2];
1522         else
1523             return (arr[$ / 2 - 1]
1524                 + arr[$ / 2]) / 2;
1525     }
1526 
1527     alias fastMedian = memoize!(median!int);
1528 
1529     assert(fastMedian([7, 5, 3]) == 5);
1530     assert(fastMedian([7, 5, 3]) == 5);
1531 
1532     assert(executed == 1);
1533 }
1534 
1535 // https://issues.dlang.org/show_bug.cgi?id=16079: memoize should work with structs
1536 @safe unittest
1537 {
1538     int executed = 0;
1539     T pickFirst(T)(T first)
1540     {
1541         executed++;
1542         return first;
1543     }
1544 
1545     struct Foo { int k; }
1546     Foo A = Foo(3);
1547 
1548     alias first = memoize!(pickFirst!Foo);
1549     assert(first(Foo(3)) == A);
1550     assert(first(Foo(3)) == A);
1551     assert(executed == 1);
1552 }
1553 
1554 // https://issues.dlang.org/show_bug.cgi?id=20439 memoize should work with void opAssign
1555 @safe unittest
1556 {
1557     static struct S
1558     {
1559         void opAssign(S) {}
1560     }
1561 
1562     assert(memoize!(() => S()) == S());
1563 }
1564 
1565 // https://issues.dlang.org/show_bug.cgi?id=16079: memoize should work with classes
1566 @system unittest // not @safe with -dip1000 due to memoize
1567 {
1568     int executed = 0;
1569     T pickFirst(T)(T first)
1570     {
1571         executed++;
1572         return first;
1573     }
1574 
1575     class Bar
1576     {
1577         size_t k;
1578         this(size_t k)
1579         {
1580             this.k = k;
1581         }
1582         override size_t toHash()
1583         {
1584             return k;
1585         }
1586         override bool opEquals(Object o)
1587         {
1588             auto b = cast(Bar) o;
1589             return b && k == b.k;
1590         }
1591     }
1592 
1593     alias firstClass = memoize!(pickFirst!Bar);
1594     assert(firstClass(new Bar(3)).k == 3);
1595     assert(firstClass(new Bar(3)).k == 3);
1596     assert(executed == 1);
1597 }
1598 
1599 // https://issues.dlang.org/show_bug.cgi?id=20302
1600 @system unittest
1601 {
1602     version (none) // TODO change `none` to `all` and fix remaining limitations
1603         struct S { const int len; }
1604     else
1605         struct S { int len; }
1606 
1607     static       string  fun000(      string str,       S s) { return str[0 .. s.len] ~ "123"; }
1608     static       string  fun001(      string str, const S s) { return str[0 .. s.len] ~ "123"; }
1609     static       string  fun010(const string str,       S s) { return str[0 .. s.len] ~ "123"; }
1610     static       string  fun011(const string str, const S s) { return str[0 .. s.len] ~ "123"; }
1611     static const(string) fun100(      string str,       S s) { return str[0 .. s.len] ~ "123"; }
1612     static const(string) fun101(      string str, const S s) { return str[0 .. s.len] ~ "123"; }
1613     static const(string) fun110(const string str,       S s) { return str[0 .. s.len] ~ "123"; }
1614     static const(string) fun111(const string str, const S s) { return str[0 .. s.len] ~ "123"; }
1615 
1616     static foreach (fun; AliasSeq!(fun000, fun001, fun010, fun011, fun100, fun101, fun110, fun111))
1617     {{
1618         alias mfun = memoize!fun;
1619         assert(mfun("abcdefgh", S(3)) == "abc123");
1620 
1621         alias mfun2 = memoize!(fun, 42);
1622         assert(mfun2("asd", S(3)) == "asd123");
1623     }}
1624 }
1625 
1626 private struct DelegateFaker(F)
1627 {
1628     import std.typecons : FuncInfo, MemberFunctionGenerator;
1629 
1630     // for @safe
1631     static F castToF(THIS)(THIS x) @trusted
1632     {
1633         return cast(F) x;
1634     }
1635 
1636     /*
1637      * What all the stuff below does is this:
1638      *--------------------
1639      * struct DelegateFaker(F) {
1640      *     extern(linkage)
1641      *     [ref] ReturnType!F doIt(Parameters!F args) [@attributes]
1642      *     {
1643      *         auto fp = cast(F) &this;
1644      *         return fp(args);
1645      *     }
1646      * }
1647      *--------------------
1648      */
1649 
1650     // We will use MemberFunctionGenerator in std.typecons.  This is a policy
1651     // configuration for generating the doIt().
1652     template GeneratingPolicy()
1653     {
1654         // Inform the genereator that we only have type information.
1655         enum WITHOUT_SYMBOL = true;
1656 
1657         // Generate the function body of doIt().
1658         template generateFunctionBody(unused...)
1659         {
1660             enum generateFunctionBody =
1661             // [ref] ReturnType doIt(Parameters args) @attributes
1662             q{
1663                 // When this function gets called, the this pointer isn't
1664                 // really a this pointer (no instance even really exists), but
1665                 // a function pointer that points to the function to be called.
1666                 // Cast it to the correct type and call it.
1667 
1668                 auto fp = castToF(&this);
1669                 return fp(args);
1670             };
1671         }
1672     }
1673     // Type information used by the generated code.
1674     alias FuncInfo_doIt = FuncInfo!(F);
1675 
1676     // Generate the member function doIt().
1677     mixin( MemberFunctionGenerator!(GeneratingPolicy!())
1678             .generateFunction!("FuncInfo_doIt", "doIt", F) );
1679 }
1680 
1681 /**
1682  * Convert a callable to a delegate with the same parameter list and
1683  * return type, avoiding heap allocations and use of auxiliary storage.
1684  *
1685  * Params:
1686  *     fp = a function pointer or an aggregate type with `opCall` defined.
1687  * Returns:
1688  *     A delegate with the context pointer pointing to nothing.
1689  *
1690  * Example:
1691  * ----
1692  * void doStuff() {
1693  *     writeln("Hello, world.");
1694  * }
1695  *
1696  * void runDelegate(void delegate() myDelegate) {
1697  *     myDelegate();
1698  * }
1699  *
1700  * auto delegateToPass = toDelegate(&doStuff);
1701  * runDelegate(delegateToPass);  // Calls doStuff, prints "Hello, world."
1702  * ----
1703  *
1704  * BUGS:
1705  * $(UL
1706  *   $(LI Does not work with `@safe` functions.)
1707  *   $(LI Ignores C-style / D-style variadic arguments.)
1708  * )
1709  */
1710 auto toDelegate(F)(auto ref F fp)
1711 if (isCallable!(F))
1712 {
1713     static if (is(F == delegate))
1714     {
1715         return fp;
1716     }
1717     else static if (is(typeof(&F.opCall) == delegate)
1718                 || (is(typeof(&F.opCall) V : V*) && is(V == function)))
1719     {
1720         return toDelegate(&fp.opCall);
1721     }
1722     else
1723     {
1724         alias DelType = typeof(&(new DelegateFaker!(F)).doIt);
1725 
1726         static struct DelegateFields {
1727             union {
1728                 DelType del;
1729                 //pragma(msg, typeof(del));
1730 
1731                 struct {
1732                     void* contextPtr;
1733                     void* funcPtr;
1734                 }
1735             }
1736         }
1737 
1738         // fp is stored in the returned delegate's context pointer.
1739         // The returned delegate's function pointer points to
1740         // DelegateFaker.doIt.
1741         DelegateFields df;
1742 
1743         df.contextPtr = cast(void*) fp;
1744 
1745         DelegateFaker!(F) dummy;
1746         auto dummyDel = &dummy.doIt;
1747         df.funcPtr = dummyDel.funcptr;
1748 
1749         return df.del;
1750     }
1751 }
1752 
1753 ///
1754 @system unittest
1755 {
1756     static int inc(ref uint num) {
1757         num++;
1758         return 8675309;
1759     }
1760 
1761     uint myNum = 0;
1762     auto incMyNumDel = toDelegate(&inc);
1763     auto returnVal = incMyNumDel(myNum);
1764     assert(myNum == 1);
1765 }
1766 
1767 @system unittest // not @safe due to toDelegate
1768 {
1769     static int inc(ref uint num) {
1770         num++;
1771         return 8675309;
1772     }
1773 
1774     uint myNum = 0;
1775     auto incMyNumDel = toDelegate(&inc);
1776     int delegate(ref uint) dg = incMyNumDel;
1777     auto returnVal = incMyNumDel(myNum);
1778     assert(myNum == 1);
1779 
1780     interface I { int opCall(); }
1781     class C: I { int opCall() { inc(myNum); return myNum;} }
1782     auto c = new C;
1783     auto i = cast(I) c;
1784 
1785     auto getvalc = toDelegate(c);
1786     assert(getvalc() == 2);
1787 
1788     auto getvali = toDelegate(i);
1789     assert(getvali() == 3);
1790 
1791     struct S1 { int opCall() { inc(myNum); return myNum; } }
1792     static assert(!is(typeof(&s1.opCall) == delegate));
1793     S1 s1;
1794     auto getvals1 = toDelegate(s1);
1795     assert(getvals1() == 4);
1796 
1797     struct S2 { static int opCall() { return 123456; } }
1798     static assert(!is(typeof(&S2.opCall) == delegate));
1799     S2 s2;
1800     auto getvals2 =&S2.opCall;
1801     assert(getvals2() == 123456);
1802 
1803     /* test for attributes */
1804     {
1805         static int refvar = 0xDeadFace;
1806 
1807         static ref int func_ref() { return refvar; }
1808         static int func_pure() pure { return 1; }
1809         static int func_nothrow() nothrow { return 2; }
1810         static int func_property() @property { return 3; }
1811         static int func_safe() @safe { return 4; }
1812         static int func_trusted() @trusted { return 5; }
1813         static int func_system() @system { return 6; }
1814         static int func_pure_nothrow() pure nothrow { return 7; }
1815         static int func_pure_nothrow_safe() pure nothrow @safe { return 8; }
1816 
1817         auto dg_ref = toDelegate(&func_ref);
1818         int delegate() pure dg_pure = toDelegate(&func_pure);
1819         int delegate() nothrow dg_nothrow = toDelegate(&func_nothrow);
1820         int delegate() @property dg_property = toDelegate(&func_property);
1821         int delegate() @safe dg_safe = toDelegate(&func_safe);
1822         int delegate() @trusted dg_trusted = toDelegate(&func_trusted);
1823         int delegate() @system dg_system = toDelegate(&func_system);
1824         int delegate() pure nothrow dg_pure_nothrow = toDelegate(&func_pure_nothrow);
1825         int delegate() @safe pure nothrow dg_pure_nothrow_safe = toDelegate(&func_pure_nothrow_safe);
1826 
1827         //static assert(is(typeof(dg_ref) == ref int delegate())); // [BUG@DMD]
1828 
1829         assert(dg_ref() == refvar);
1830         assert(dg_pure() == 1);
1831         assert(dg_nothrow() == 2);
1832         assert(dg_property() == 3);
1833         assert(dg_safe() == 4);
1834         assert(dg_trusted() == 5);
1835         assert(dg_system() == 6);
1836         assert(dg_pure_nothrow() == 7);
1837         assert(dg_pure_nothrow_safe() == 8);
1838     }
1839     /* test for linkage */
1840     {
1841         struct S
1842         {
1843             extern(C) static void xtrnC() {}
1844             extern(D) static void xtrnD() {}
1845         }
1846         auto dg_xtrnC = toDelegate(&S.xtrnC);
1847         auto dg_xtrnD = toDelegate(&S.xtrnD);
1848         static assert(! is(typeof(dg_xtrnC) == typeof(dg_xtrnD)));
1849     }
1850 }
1851 
1852 /**
1853  * Passes the fields of a struct as arguments to a function.
1854  *
1855  * Can be used with a $(LINK2 https://dlang.org/spec/expression.html#function_literals,
1856  * function literal) to give temporary names to the fields of a struct or
1857  * tuple.
1858  *
1859  * Params:
1860  *   fun = Callable that the struct's fields will be passed to.
1861  *
1862  * Returns:
1863  *   A function that accepts a single struct as an argument and passes its
1864  *   fields to `fun` when called.
1865  */
1866 template bind(alias fun)
1867 {
1868     /**
1869      * Params:
1870      *   args = The struct or tuple whose fields will be used as arguments.
1871      *
1872      * Returns: `fun(args.tupleof)`
1873      */
1874     auto ref bind(T)(auto ref T args)
1875     if (is(T == struct))
1876     {
1877         import std.meta : Map = staticMap;
1878         import core.lifetime : move;
1879 
1880         // Forwards the i'th member of `args`
1881         // Needed because core.lifetime.forward doesn't work on struct members
1882         template forwardArg(size_t i)
1883         {
1884             static if (__traits(isRef, args) || !is(typeof(move(args.tupleof[i]))))
1885                 enum forwardArg = "args.tupleof[" ~ toCtString!i ~ "], ";
1886             else
1887                 enum forwardArg = "move(args.tupleof[" ~ toCtString!i ~ "]), ";
1888         }
1889 
1890         static if (args.tupleof.length == 0)
1891             enum argList = "";
1892         else
1893             alias argList = Map!(forwardArg, Iota!(args.tupleof.length));
1894 
1895         return mixin("fun(", argList, ")");
1896     }
1897 }
1898 
1899 /// Giving names to tuple elements
1900 @safe unittest
1901 {
1902     import std.typecons : tuple;
1903 
1904     auto name = tuple("John", "Doe");
1905     string full = name.bind!((first, last) => first ~ " " ~ last);
1906     assert(full == "John Doe");
1907 }
1908 
1909 /// Passing struct fields to a function
1910 @safe unittest
1911 {
1912     import std.algorithm.comparison : min, max;
1913 
1914     struct Pair
1915     {
1916         int a;
1917         int b;
1918     }
1919 
1920     auto p = Pair(123, 456);
1921     assert(p.bind!min == 123); // min(p.a, p.b)
1922     assert(p.bind!max == 456); // max(p.a, p.b)
1923 }
1924 
1925 /// In a range pipeline
1926 @safe unittest
1927 {
1928     import std.algorithm.iteration : map, filter;
1929     import std.algorithm.comparison : equal;
1930     import std.typecons : tuple;
1931 
1932     auto ages = [
1933         tuple("Alice", 35),
1934         tuple("Bob",   64),
1935         tuple("Carol", 21),
1936         tuple("David", 39),
1937         tuple("Eve",   50)
1938     ];
1939 
1940     auto overForty = ages
1941         .filter!(bind!((name, age) => age > 40))
1942         .map!(bind!((name, age) => name));
1943 
1944     assert(overForty.equal(["Bob", "Eve"]));
1945 }
1946 
1947 // Zero arguments
1948 @safe unittest
1949 {
1950     struct Empty {}
1951 
1952     assert(Empty().bind!(() => 123) == 123);
1953 }
1954 
1955 // Non-copyable arguments
1956 @safe unittest
1957 {
1958     import std.typecons : tuple;
1959 
1960     static struct NoCopy
1961     {
1962         int n;
1963         @disable this(this);
1964     }
1965 
1966     static struct Pair
1967     {
1968         NoCopy a, b;
1969     }
1970 
1971     static auto fun(NoCopy a, NoCopy b)
1972     {
1973         return tuple(a.n, b.n);
1974     }
1975 
1976     auto expected = fun(NoCopy(1), NoCopy(2));
1977     assert(Pair(NoCopy(1), NoCopy(2)).bind!fun == expected);
1978 }
1979 
1980 // ref arguments
1981 @safe unittest
1982 {
1983     import std.typecons : tuple;
1984 
1985     auto t = tuple(123, 456);
1986     t.bind!((ref int a, int b) { a = 789; b = 1011; });
1987 
1988     assert(t[0] == 789);
1989     assert(t[1] == 456);
1990 }
1991 
1992 // auto ref arguments
1993 @safe unittest
1994 {
1995     import std.typecons : tuple;
1996 
1997     auto t = tuple(123);
1998     t.bind!((auto ref x) {
1999         static assert(__traits(isRef, x));
2000     });
2001     tuple(123).bind!((auto ref x) {
2002         static assert(!__traits(isRef, x));
2003     });
2004 }
2005