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