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 $(BOOKTABLE ,
12 $(TR $(TH Function Name) $(TH Description)
13 )
14     $(TR $(TD $(LREF adjoin))
15         $(TD Joins a couple of functions into one that executes the original
16         functions independently and returns a tuple with all the results.
17     ))
18     $(TR $(TD $(LREF compose), $(LREF pipe))
19         $(TD Join a couple of functions into one that executes the original
20         functions one after the other, using one function's result for the next
21         function's argument.
22     ))
23     $(TR $(TD $(LREF forward))
24         $(TD Forwards function arguments while saving ref-ness.
25     ))
26     $(TR $(TD $(LREF lessThan), $(LREF greaterThan), $(LREF equalTo))
27         $(TD Ready-made predicate functions to compare two values.
28     ))
29     $(TR $(TD $(LREF memoize))
30         $(TD Creates a function that caches its result for fast re-evaluation.
31     ))
32     $(TR $(TD $(LREF not))
33         $(TD Creates a function that negates another.
34     ))
35     $(TR $(TD $(LREF partial))
36         $(TD Creates a function that binds the first argument of a given function
37         to a given value.
38     ))
39     $(TR $(TD $(LREF reverseArgs), $(LREF binaryReverseArgs))
40         $(TD Predicate that reverses the order of its arguments.
41     ))
42     $(TR $(TD $(LREF toDelegate))
43         $(TD Converts a callable to a delegate.
44     ))
45     $(TR $(TD $(LREF unaryFun), $(LREF binaryFun))
46         $(TD Create a unary or binary function from a string. Most often
47         used when defining algorithms on ranges.
48     ))
49 )
50 
51 Copyright: Copyright Andrei Alexandrescu 2008 - 2009.
52 License:   $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
53 Authors:   $(HTTP erdani.org, Andrei Alexandrescu)
54 Source:    $(PHOBOSSRC std/_functional.d)
55 */
56 /*
57          Copyright Andrei Alexandrescu 2008 - 2009.
58 Distributed under the Boost Software License, Version 1.0.
59    (See accompanying file LICENSE_1_0.txt or copy at
60          http://www.boost.org/LICENSE_1_0.txt)
61 */
62 module std.functional;
63 
64 import std.meta; // AliasSeq, Reverse
65 import std.traits; // isCallable, Parameters
66 
67 
needOpCallAlias(alias fun)68 private template needOpCallAlias(alias fun)
69 {
70     /* Determine whether or not unaryFun and binaryFun need to alias to fun or
71      * fun.opCall. Basically, fun is a function object if fun(...) compiles. We
72      * want is(unaryFun!fun) (resp., is(binaryFun!fun)) to be true if fun is
73      * any function object. There are 4 possible cases:
74      *
75      *  1) fun is the type of a function object with static opCall;
76      *  2) fun is an instance of a function object with static opCall;
77      *  3) fun is the type of a function object with non-static opCall;
78      *  4) fun is an instance of a function object with non-static opCall.
79      *
80      * In case (1), is(unaryFun!fun) should compile, but does not if unaryFun
81      * aliases itself to fun, because typeof(fun) is an error when fun itself
82      * is a type. So it must be aliased to fun.opCall instead. All other cases
83      * should be aliased to fun directly.
84      */
85     static if (is(typeof(fun.opCall) == function))
86     {
87         enum needOpCallAlias = !is(typeof(fun)) && __traits(compiles, () {
88             return fun(Parameters!fun.init);
89         });
90     }
91     else
92         enum needOpCallAlias = false;
93 }
94 
95 /**
96 Transforms a string representing an expression into a unary
97 function. The string must either use symbol name $(D a) as
98 the parameter or provide the symbol via the $(D parmName) argument.
99 If $(D fun) is not a string, $(D unaryFun) aliases itself away to $(D fun).
100 */
101 
102 template unaryFun(alias fun, string parmName = "a")
103 {
104     static if (is(typeof(fun) : string))
105     {
106         static if (!fun._ctfeMatchUnary(parmName))
107         {
108             import std.algorithm, std.conv, std.exception, std.math, std.range, std.string;
109             import std.meta, std.traits, std.typecons;
110         }
unaryFun(ElementType)111         auto unaryFun(ElementType)(auto ref ElementType __a)
112         {
113             mixin("alias " ~ parmName ~ " = __a ;");
114             return mixin(fun);
115         }
116     }
117     else static if (needOpCallAlias!fun)
118     {
119         // Issue 9906
120         alias unaryFun = fun.opCall;
121     }
122     else
123     {
124         alias unaryFun = fun;
125     }
126 }
127 
128 ///
129 @safe unittest
130 {
131     // Strings are compiled into functions:
132     alias isEven = unaryFun!("(a & 1) == 0");
133     assert(isEven(2) && !isEven(1));
134 }
135 
136 @safe unittest
137 {
f1(int a)138     static int f1(int a) { return a + 1; }
139     static assert(is(typeof(unaryFun!(f1)(1)) == int));
140     assert(unaryFun!(f1)(41) == 42);
f2(int a)141     int f2(int a) { return a + 1; }
142     static assert(is(typeof(unaryFun!(f2)(1)) == int));
143     assert(unaryFun!(f2)(41) == 42);
144     assert(unaryFun!("a + 1")(41) == 42);
145     //assert(unaryFun!("return a + 1;")(41) == 42);
146 
147     int num = 41;
148     assert(unaryFun!"a + 1"(num) == 42);
149 
150     // Issue 9906
151     struct Seen
152     {
opCallSeen153         static bool opCall(int n) { return true; }
154     }
155     static assert(needOpCallAlias!Seen);
156     static assert(is(typeof(unaryFun!Seen(1))));
157     assert(unaryFun!Seen(1));
158 
159     Seen s;
160     static assert(!needOpCallAlias!s);
161     static assert(is(typeof(unaryFun!s(1))));
162     assert(unaryFun!s(1));
163 
164     struct FuncObj
165     {
opCallFuncObj166         bool opCall(int n) { return true; }
167     }
168     FuncObj fo;
169     static assert(!needOpCallAlias!fo);
170     static assert(is(typeof(unaryFun!fo)));
171     assert(unaryFun!fo(1));
172 
173     // Function object with non-static opCall can only be called with an
174     // instance, not with merely the type.
175     static assert(!is(typeof(unaryFun!FuncObj)));
176 }
177 
178 /**
179 Transforms a string representing an expression into a binary function. The
180 string must either use symbol names $(D a) and $(D b) as the parameters or
181 provide the symbols via the $(D parm1Name) and $(D parm2Name) arguments.
182 If $(D fun) is not a string, $(D binaryFun) aliases itself away to
183 $(D fun).
184 */
185 
186 template binaryFun(alias fun, string parm1Name = "a",
187         string parm2Name = "b")
188 {
189     static if (is(typeof(fun) : string))
190     {
191         static if (!fun._ctfeMatchBinary(parm1Name, parm2Name))
192         {
193             import std.algorithm, std.conv, std.exception, std.math, std.range, std.string;
194             import std.meta, std.traits, std.typecons;
195         }
binaryFun(ElementType1,ElementType2)196         auto binaryFun(ElementType1, ElementType2)
197             (auto ref ElementType1 __a, auto ref ElementType2 __b)
198         {
199             mixin("alias "~parm1Name~" = __a ;");
200             mixin("alias "~parm2Name~" = __b ;");
201             return mixin(fun);
202         }
203     }
204     else static if (needOpCallAlias!fun)
205     {
206         // Issue 9906
207         alias binaryFun = fun.opCall;
208     }
209     else
210     {
211         alias binaryFun = fun;
212     }
213 }
214 
215 ///
216 @safe unittest
217 {
218     alias less = binaryFun!("a < b");
219     assert(less(1, 2) && !less(2, 1));
220     alias greater = binaryFun!("a > b");
221     assert(!greater("1", "2") && greater("2", "1"));
222 }
223 
224 @safe unittest
225 {
f1(int a,string b)226     static int f1(int a, string b) { return a + 1; }
227     static assert(is(typeof(binaryFun!(f1)(1, "2")) == int));
228     assert(binaryFun!(f1)(41, "a") == 42);
f2(int a,string b)229     string f2(int a, string b) { return b ~ "2"; }
230     static assert(is(typeof(binaryFun!(f2)(1, "1")) == string));
231     assert(binaryFun!(f2)(1, "4") == "42");
232     assert(binaryFun!("a + b")(41, 1) == 42);
233     //@@BUG
234     //assert(binaryFun!("return a + b;")(41, 1) == 42);
235 
236     // Issue 9906
237     struct Seen
238     {
opCallSeen239         static bool opCall(int x, int y) { return true; }
240     }
241     static assert(is(typeof(binaryFun!Seen)));
242     assert(binaryFun!Seen(1,1));
243 
244     struct FuncObj
245     {
opCallFuncObj246         bool opCall(int x, int y) { return true; }
247     }
248     FuncObj fo;
249     static assert(!needOpCallAlias!fo);
250     static assert(is(typeof(binaryFun!fo)));
251     assert(unaryFun!fo(1,1));
252 
253     // Function object with non-static opCall can only be called with an
254     // instance, not with merely the type.
255     static assert(!is(typeof(binaryFun!FuncObj)));
256 }
257 
258 // skip all ASCII chars except a .. z, A .. Z, 0 .. 9, '_' and '.'.
_ctfeSkipOp(ref string op)259 private uint _ctfeSkipOp(ref string op)
260 {
261     if (!__ctfe) assert(false);
262     import std.ascii : isASCII, isAlphaNum;
263     immutable oldLength = op.length;
264     while (op.length)
265     {
266         immutable front = op[0];
267         if (front.isASCII() && !(front.isAlphaNum() || front == '_' || front == '.'))
268             op = op[1..$];
269         else
270             break;
271     }
272     return oldLength != op.length;
273 }
274 
275 // skip all digits
_ctfeSkipInteger(ref string op)276 private uint _ctfeSkipInteger(ref string op)
277 {
278     if (!__ctfe) assert(false);
279     import std.ascii : isDigit;
280     immutable oldLength = op.length;
281     while (op.length)
282     {
283         immutable front = op[0];
284         if (front.isDigit())
285             op = op[1..$];
286         else
287             break;
288     }
289     return oldLength != op.length;
290 }
291 
292 // skip name
_ctfeSkipName(ref string op,string name)293 private uint _ctfeSkipName(ref string op, string name)
294 {
295     if (!__ctfe) assert(false);
296     if (op.length >= name.length && op[0 .. name.length] == name)
297     {
298         op = op[name.length..$];
299         return 1;
300     }
301     return 0;
302 }
303 
304 // returns 1 if $(D fun) is trivial unary function
_ctfeMatchUnary(string fun,string name)305 private uint _ctfeMatchUnary(string fun, string name)
306 {
307     if (!__ctfe) assert(false);
308     fun._ctfeSkipOp();
309     for (;;)
310     {
311         immutable h = fun._ctfeSkipName(name) + fun._ctfeSkipInteger();
312         if (h == 0)
313         {
314             fun._ctfeSkipOp();
315             break;
316         }
317         else if (h == 1)
318         {
319             if (!fun._ctfeSkipOp())
320                 break;
321         }
322         else
323             return 0;
324     }
325     return fun.length == 0;
326 }
327 
328 @safe unittest
329 {
330     static assert(!_ctfeMatchUnary("sqrt(ё)", "ё"));
331     static assert(!_ctfeMatchUnary("ё.sqrt", "ё"));
332     static assert(!_ctfeMatchUnary(".ё+ё", "ё"));
333     static assert(!_ctfeMatchUnary("_ё+ё", "ё"));
334     static assert(!_ctfeMatchUnary("ёё", "ё"));
335     static assert(_ctfeMatchUnary("a+a", "a"));
336     static assert(_ctfeMatchUnary("a + 10", "a"));
337     static assert(_ctfeMatchUnary("4 == a", "a"));
338     static assert(_ctfeMatchUnary("2 == a", "a"));
339     static assert(_ctfeMatchUnary("1 != a", "a"));
340     static assert(_ctfeMatchUnary("a != 4", "a"));
341     static assert(_ctfeMatchUnary("a< 1", "a"));
342     static assert(_ctfeMatchUnary("434 < a", "a"));
343     static assert(_ctfeMatchUnary("132 > a", "a"));
344     static assert(_ctfeMatchUnary("123 >a", "a"));
345     static assert(_ctfeMatchUnary("a>82", "a"));
346     static assert(_ctfeMatchUnary("ё>82", "ё"));
347     static assert(_ctfeMatchUnary("ё[ё(ё)]", "ё"));
348     static assert(_ctfeMatchUnary("ё[21]", "ё"));
349 }
350 
351 // returns 1 if $(D fun) is trivial binary function
_ctfeMatchBinary(string fun,string name1,string name2)352 private uint _ctfeMatchBinary(string fun, string name1, string name2)
353 {
354     if (!__ctfe) assert(false);
355     fun._ctfeSkipOp();
356     for (;;)
357     {
358         immutable h = fun._ctfeSkipName(name1) + fun._ctfeSkipName(name2) + fun._ctfeSkipInteger();
359         if (h == 0)
360         {
361             fun._ctfeSkipOp();
362             break;
363         }
364         else if (h == 1)
365         {
366             if (!fun._ctfeSkipOp())
367                 break;
368         }
369         else
370             return 0;
371     }
372     return fun.length == 0;
373 }
374 
375 @safe unittest
376 {
377 
378     static assert(!_ctfeMatchBinary("sqrt(ё)", "ё", "b"));
379     static assert(!_ctfeMatchBinary("ё.sqrt", "ё", "b"));
380     static assert(!_ctfeMatchBinary(".ё+ё", "ё", "b"));
381     static assert(!_ctfeMatchBinary("_ё+ё", "ё", "b"));
382     static assert(!_ctfeMatchBinary("ёё", "ё", "b"));
383     static assert(_ctfeMatchBinary("a+a", "a", "b"));
384     static assert(_ctfeMatchBinary("a + 10", "a", "b"));
385     static assert(_ctfeMatchBinary("4 == a", "a", "b"));
386     static assert(_ctfeMatchBinary("2 == a", "a", "b"));
387     static assert(_ctfeMatchBinary("1 != a", "a", "b"));
388     static assert(_ctfeMatchBinary("a != 4", "a", "b"));
389     static assert(_ctfeMatchBinary("a< 1", "a", "b"));
390     static assert(_ctfeMatchBinary("434 < a", "a", "b"));
391     static assert(_ctfeMatchBinary("132 > a", "a", "b"));
392     static assert(_ctfeMatchBinary("123 >a", "a", "b"));
393     static assert(_ctfeMatchBinary("a>82", "a", "b"));
394     static assert(_ctfeMatchBinary("ё>82", "ё", "q"));
395     static assert(_ctfeMatchBinary("ё[ё(10)]", "ё", "q"));
396     static assert(_ctfeMatchBinary("ё[21]", "ё", "q"));
397 
398     static assert(!_ctfeMatchBinary("sqrt(ё)+b", "b", "ё"));
399     static assert(!_ctfeMatchBinary("ё.sqrt-b", "b", "ё"));
400     static assert(!_ctfeMatchBinary(".ё+b", "b", "ё"));
401     static assert(!_ctfeMatchBinary("_b+ё", "b", "ё"));
402     static assert(!_ctfeMatchBinary("ba", "b", "a"));
403     static assert(_ctfeMatchBinary("a+b", "b", "a"));
404     static assert(_ctfeMatchBinary("a + b", "b", "a"));
405     static assert(_ctfeMatchBinary("b == a", "b", "a"));
406     static assert(_ctfeMatchBinary("b == a", "b", "a"));
407     static assert(_ctfeMatchBinary("b != a", "b", "a"));
408     static assert(_ctfeMatchBinary("a != b", "b", "a"));
409     static assert(_ctfeMatchBinary("a< b", "b", "a"));
410     static assert(_ctfeMatchBinary("b < a", "b", "a"));
411     static assert(_ctfeMatchBinary("b > a", "b", "a"));
412     static assert(_ctfeMatchBinary("b >a", "b", "a"));
413     static assert(_ctfeMatchBinary("a>b", "b", "a"));
414     static assert(_ctfeMatchBinary("ё>b", "b", "ё"));
415     static assert(_ctfeMatchBinary("b[ё(-1)]", "b", "ё"));
416     static assert(_ctfeMatchBinary("ё[-21]", "b", "ё"));
417 }
418 
419 //undocumented
420 template safeOp(string S)
421 if (S=="<"||S==">"||S=="<="||S==">="||S=="=="||S=="!=")
422 {
423     import std.traits : isIntegral;
424     private bool unsafeOp(ElementType1, ElementType2)(ElementType1 a, ElementType2 b) pure
425         if (isIntegral!ElementType1 && isIntegral!ElementType2)
426     {
427         import std.traits : CommonType;
428         alias T = CommonType!(ElementType1, ElementType2);
429         return mixin("cast(T)a "~S~" cast(T) b");
430     }
431 
safeOp(T0,T1)432     bool safeOp(T0, T1)(auto ref T0 a, auto ref T1 b)
433     {
434         import std.traits : mostNegative;
435         static if (isIntegral!T0 && isIntegral!T1 &&
436                    (mostNegative!T0 < 0) != (mostNegative!T1 < 0))
437         {
438             static if (S == "<=" || S == "<")
439             {
440                 static if (mostNegative!T0 < 0)
441                     immutable result = a < 0 || unsafeOp(a, b);
442                 else
443                     immutable result = b >= 0 && unsafeOp(a, b);
444             }
445             else
446             {
447                 static if (mostNegative!T0 < 0)
448                     immutable result = a >= 0 && unsafeOp(a, b);
449                 else
450                     immutable result = b < 0 || unsafeOp(a, b);
451             }
452         }
453         else
454         {
455             static assert(is(typeof(mixin("a "~S~" b"))),
456                 "Invalid arguments: Cannot compare types " ~ T0.stringof ~ " and " ~ T1.stringof ~ ".");
457 
458             immutable result = mixin("a "~S~" b");
459         }
460         return result;
461     }
462 }
463 
464 @safe unittest //check user defined types
465 {
466     import std.algorithm.comparison : equal;
467     struct Foo
468     {
469         int a;
opEqualsFoo470         auto opEquals(Foo foo)
471         {
472             return a == foo.a;
473         }
474     }
475     assert(safeOp!"!="(Foo(1), Foo(2)));
476 }
477 
478 /**
479    Predicate that returns $(D_PARAM a < b).
480    Correctly compares signed and unsigned integers, ie. -1 < 2U.
481 */
482 alias lessThan = safeOp!"<";
483 
484 ///
485 pure @safe @nogc nothrow unittest
486 {
487     assert(lessThan(2, 3));
488     assert(lessThan(2U, 3U));
489     assert(lessThan(2, 3.0));
490     assert(lessThan(-2, 3U));
491     assert(lessThan(2, 3U));
492     assert(!lessThan(3U, -2));
493     assert(!lessThan(3U, 2));
494     assert(!lessThan(0, 0));
495     assert(!lessThan(0U, 0));
496     assert(!lessThan(0, 0U));
497 }
498 
499 /**
500    Predicate that returns $(D_PARAM a > b).
501    Correctly compares signed and unsigned integers, ie. 2U > -1.
502 */
503 alias greaterThan = safeOp!">";
504 
505 ///
506 @safe unittest
507 {
508     assert(!greaterThan(2, 3));
509     assert(!greaterThan(2U, 3U));
510     assert(!greaterThan(2, 3.0));
511     assert(!greaterThan(-2, 3U));
512     assert(!greaterThan(2, 3U));
513     assert(greaterThan(3U, -2));
514     assert(greaterThan(3U, 2));
515     assert(!greaterThan(0, 0));
516     assert(!greaterThan(0U, 0));
517     assert(!greaterThan(0, 0U));
518 }
519 
520 /**
521    Predicate that returns $(D_PARAM a == b).
522    Correctly compares signed and unsigned integers, ie. !(-1 == ~0U).
523 */
524 alias equalTo = safeOp!"==";
525 
526 ///
527 @safe unittest
528 {
529     assert(equalTo(0U, 0));
530     assert(equalTo(0, 0U));
531     assert(!equalTo(-1, ~0U));
532 }
533 /**
534    N-ary predicate that reverses the order of arguments, e.g., given
535    $(D pred(a, b, c)), returns $(D pred(c, b, a)).
536 */
reverseArgs(alias pred)537 template reverseArgs(alias pred)
538 {
539     auto reverseArgs(Args...)(auto ref Args args)
540         if (is(typeof(pred(Reverse!args))))
541     {
542         return pred(Reverse!args);
543     }
544 }
545 
546 ///
547 @safe unittest
548 {
549     alias gt = reverseArgs!(binaryFun!("a < b"));
550     assert(gt(2, 1) && !gt(1, 1));
551     int x = 42;
xyz(int a,int b)552     bool xyz(int a, int b) { return a * x < b / x; }
553     auto foo = &xyz;
554     foo(4, 5);
555     alias zyx = reverseArgs!(foo);
556     assert(zyx(5, 4) == foo(4, 5));
557 }
558 
559 ///
560 @safe unittest
561 {
abc(int a,int b,int c)562     int abc(int a, int b, int c) { return a * b + c; }
563     alias cba = reverseArgs!abc;
564     assert(abc(91, 17, 32) == cba(32, 17, 91));
565 }
566 
567 ///
568 @safe unittest
569 {
a(int a)570     int a(int a) { return a * 2; }
571     alias _a = reverseArgs!a;
572     assert(a(2) == _a(2));
573 }
574 
575 ///
576 @safe unittest
577 {
b()578     int b() { return 4; }
579     alias _b = reverseArgs!b;
580     assert(b() == _b());
581 }
582 
583 /**
584    Binary predicate that reverses the order of arguments, e.g., given
585    $(D pred(a, b)), returns $(D pred(b, a)).
586 */
binaryReverseArgs(alias pred)587 template binaryReverseArgs(alias pred)
588 {
589     auto binaryReverseArgs(ElementType1, ElementType2)
590             (auto ref ElementType1 a, auto ref ElementType2 b)
591     {
592         return pred(b, a);
593     }
594 }
595 
596 ///
597 @safe unittest
598 {
599     alias gt = binaryReverseArgs!(binaryFun!("a < b"));
600     assert(gt(2, 1) && !gt(1, 1));
601 }
602 
603 ///
604 @safe unittest
605 {
606     int x = 42;
xyz(int a,int b)607     bool xyz(int a, int b) { return a * x < b / x; }
608     auto foo = &xyz;
609     foo(4, 5);
610     alias zyx = binaryReverseArgs!(foo);
611     assert(zyx(5, 4) == foo(4, 5));
612 }
613 
614 /**
615 Negates predicate $(D pred).
616  */
not(alias pred)617 template not(alias pred)
618 {
619     auto not(T...)(auto ref T args)
620     {
621         static if (is(typeof(!pred(args))))
622             return !pred(args);
623         else static if (T.length == 1)
624             return !unaryFun!pred(args);
625         else static if (T.length == 2)
626             return !binaryFun!pred(args);
627         else
628             static assert(0);
629     }
630 }
631 
632 ///
633 @safe unittest
634 {
635     import std.algorithm.searching : find;
636     import std.functional;
637     import std.uni : isWhite;
638     string a = "   Hello, world!";
639     assert(find!(not!isWhite)(a) == "Hello, world!");
640 }
641 
642 @safe unittest
643 {
644     assert(not!"a != 5"(5));
645     assert(not!"a != b"(5, 5));
646 
647     assert(not!(() => false)());
648     assert(not!(a => a != 5)(5));
649     assert(not!((a, b) => a != b)(5, 5));
650     assert(not!((a, b, c) => a * b * c != 125 )(5, 5, 5));
651 }
652 
653 /**
654 $(LINK2 http://en.wikipedia.org/wiki/Partial_application, Partially
655 applies) $(D_PARAM fun) by tying its first argument to $(D_PARAM arg).
656  */
partial(alias fun,alias arg)657 template partial(alias fun, alias arg)
658 {
659     static if (is(typeof(fun) == delegate) || is(typeof(fun) == function))
660     {
661         import std.traits : ReturnType;
662         ReturnType!fun partial(Parameters!fun[1..$] args2)
663         {
664             return fun(arg, args2);
665         }
666     }
667     else
668     {
669         auto partial(Ts...)(Ts args2)
670         {
671             static if (is(typeof(fun(arg, args2))))
672             {
673                 return fun(arg, args2);
674             }
675             else
676             {
677                 static string errormsg()
678                 {
679                     string msg = "Cannot call '" ~ fun.stringof ~ "' with arguments " ~
680                         "(" ~ arg.stringof;
681                     foreach (T; Ts)
682                         msg ~= ", " ~ T.stringof;
683                     msg ~= ").";
684                     return msg;
685                 }
686                 static assert(0, errormsg());
687             }
688         }
689     }
690 }
691 
692 ///
693 @safe unittest
694 {
fun(int a,int b)695     int fun(int a, int b) { return a + b; }
696     alias fun5 = partial!(fun, 5);
697     assert(fun5(6) == 11);
698     // Note that in most cases you'd use an alias instead of a value
699     // assignment. Using an alias allows you to partially evaluate template
700     // functions without committing to a particular type of the function.
701 }
702 
703 // tests for partially evaluating callables
704 @safe unittest
705 {
f1(int a,int b)706     static int f1(int a, int b) { return a + b; }
707     assert(partial!(f1, 5)(6) == 11);
708 
f2(int a,int b)709     int f2(int a, int b) { return a + b; }
710     int x = 5;
711     assert(partial!(f2, x)(6) == 11);
712     x = 7;
713     assert(partial!(f2, x)(6) == 13);
714     static assert(partial!(f2, 5)(6) == 11);
715 
716     auto dg = &f2;
717     auto f3 = &partial!(dg, x);
718     assert(f3(6) == 13);
719 
funOneArg(int a)720     static int funOneArg(int a) { return a; }
721     assert(partial!(funOneArg, 1)() == 1);
722 
funThreeArgs(int a,int b,int c)723     static int funThreeArgs(int a, int b, int c) { return a + b + c; }
724     alias funThreeArgs1 = partial!(funThreeArgs, 1);
725     assert(funThreeArgs1(2, 3) == 6);
726     static assert(!is(typeof(funThreeArgs1(2))));
727 
728     enum xe = 5;
729     alias fe = partial!(f2, xe);
730     static assert(fe(6) == 11);
731 }
732 
733 // tests for partially evaluating templated/overloaded callables
734 @safe unittest
735 {
add(A,B)736     static auto add(A, B)(A x, B y)
737     {
738         return x + y;
739     }
740 
741     alias add5 = partial!(add, 5);
742     assert(add5(6) == 11);
743     static assert(!is(typeof(add5())));
744     static assert(!is(typeof(add5(6, 7))));
745 
746     // taking address of templated partial evaluation needs explicit type
747     auto dg = &add5!(int);
748     assert(dg(6) == 11);
749 
750     int x = 5;
751     alias addX = partial!(add, x);
752     assert(addX(6) == 11);
753 
754     static struct Callable
755     {
opCallCallable756         static string opCall(string a, string b) { return a ~ b; }
opCallCallable757         int opCall(int a, int b) { return a * b; }
opCallCallable758         double opCall(double a, double b) { return a + b; }
759     }
760     Callable callable;
761     assert(partial!(Callable, "5")("6") == "56");
762     assert(partial!(callable, 5)(6) == 30);
763     assert(partial!(callable, 7.0)(3.0) == 7.0 + 3.0);
764 
765     static struct TCallable
766     {
opCallTCallable767         auto opCall(A, B)(A a, B b)
768         {
769             return a + b;
770         }
771     }
772     TCallable tcallable;
773     assert(partial!(tcallable, 5)(6) == 11);
774     static assert(!is(typeof(partial!(tcallable, "5")(6))));
775 
funOneArg(A)776     static A funOneArg(A)(A a) { return a; }
777     alias funOneArg1 = partial!(funOneArg, 1);
778     assert(funOneArg1() == 1);
779 
funThreeArgs(A,B,C)780     static auto funThreeArgs(A, B, C)(A a, B b, C c) { return a + b + c; }
781     alias funThreeArgs1 = partial!(funThreeArgs, 1);
782     assert(funThreeArgs1(2, 3) == 6);
783     static assert(!is(typeof(funThreeArgs1(1))));
784 
785     auto dg2 = &funOneArg1!();
786     assert(dg2() == 1);
787 }
788 
789 /**
790 Takes multiple functions and adjoins them together. The result is a
791 $(REF Tuple, std,typecons) with one element per passed-in function. Upon
792 invocation, the returned tuple is the adjoined results of all
793 functions.
794 
795 Note: In the special case where only a single function is provided
796 ($(D F.length == 1)), adjoin simply aliases to the single passed function
797 ($(D F[0])).
798 */
799 template adjoin(F...)
800 if (F.length == 1)
801 {
802     alias adjoin = F[0];
803 }
804 /// ditto
805 template adjoin(F...)
806 if (F.length > 1)
807 {
adjoin(V...)808     auto adjoin(V...)(auto ref V a)
809     {
810         import std.typecons : tuple;
811         static if (F.length == 2)
812         {
813             return tuple(F[0](a), F[1](a));
814         }
815         else static if (F.length == 3)
816         {
817             return tuple(F[0](a), F[1](a), F[2](a));
818         }
819         else
820         {
821             import std.format : format;
822             import std.range : iota;
823             return mixin (q{tuple(%(F[%s](a)%|, %))}.format(iota(0, F.length)));
824         }
825     }
826 }
827 
828 ///
829 @safe unittest
830 {
831     import std.functional, std.typecons : Tuple;
f1(int a)832     static bool f1(int a) { return a != 0; }
f2(int a)833     static int f2(int a) { return a / 2; }
834     auto x = adjoin!(f1, f2)(5);
835     assert(is(typeof(x) == Tuple!(bool, int)));
836     assert(x[0] == true && x[1] == 2);
837 }
838 
839 @safe unittest
840 {
841     import std.typecons : Tuple;
F1(int a)842     static bool F1(int a) { return a != 0; }
843     auto x1 = adjoin!(F1)(5);
F2(int a)844     static int F2(int a) { return a / 2; }
845     auto x2 = adjoin!(F1, F2)(5);
846     assert(is(typeof(x2) == Tuple!(bool, int)));
847     assert(x2[0] && x2[1] == 2);
848     auto x3 = adjoin!(F1, F2, F2)(5);
849     assert(is(typeof(x3) == Tuple!(bool, int, int)));
850     assert(x3[0] && x3[1] == 2 && x3[2] == 2);
851 
F4(int a)852     bool F4(int a) { return a != x1; }
853     alias eff4 = adjoin!(F4);
854     static struct S
855     {
856         bool delegate(int) @safe store;
funS857         int fun() { return 42 + store(5); }
858     }
859     S s;
860     s.store = (int a) { return eff4(a); };
861     auto x4 = s.fun();
862     assert(x4 == 43);
863 }
864 
865 @safe unittest
866 {
867     import std.meta : staticMap;
868     import std.typecons : Tuple, tuple;
869     alias funs = staticMap!(unaryFun, "a", "a * 2", "a * 3", "a * a", "-a");
870     alias afun = adjoin!funs;
871     assert(afun(5) == tuple(5, 10, 15, 25, -5));
872 
873     static class C{}
874     alias IC = immutable(C);
foo()875     IC foo(){return typeof(return).init;}
876     Tuple!(IC, IC, IC, IC) ret1 = adjoin!(foo, foo, foo, foo)();
877 
878     static struct S{int* p;}
879     alias IS = immutable(S);
bar()880     IS bar(){return typeof(return).init;}
881     enum Tuple!(IS, IS, IS, IS) ret2 = adjoin!(bar, bar, bar, bar)();
882 }
883 
884 /**
885    Composes passed-in functions $(D fun[0], fun[1], ...) returning a
886    function $(D f(x)) that in turn returns $(D
887    fun[0](fun[1](...(x)))...). Each function can be a regular
888    functions, a delegate, or a string.
889 
890    See_Also: $(LREF pipe)
891 */
compose(fun...)892 template compose(fun...)
893 {
894     static if (fun.length == 1)
895     {
896         alias compose = unaryFun!(fun[0]);
897     }
898     else static if (fun.length == 2)
899     {
900         // starch
901         alias fun0 = unaryFun!(fun[0]);
902         alias fun1 = unaryFun!(fun[1]);
903 
904         // protein: the core composition operation
905         typeof({ E a; return fun0(fun1(a)); }()) compose(E)(E a)
906         {
907             return fun0(fun1(a));
908         }
909     }
910     else
911     {
912         // protein: assembling operations
913         alias compose = compose!(fun[0], compose!(fun[1 .. $]));
914     }
915 }
916 
917 ///
918 @safe unittest
919 {
920     import std.algorithm.comparison : equal;
921     import std.algorithm.iteration : map;
922     import std.array : split;
923     import std.conv : to;
924 
925     // First split a string in whitespace-separated tokens and then
926     // convert each token into an integer
927     assert(compose!(map!(to!(int)), split)("1 2 3").equal([1, 2, 3]));
928 }
929 
930 /**
931    Pipes functions in sequence. Offers the same functionality as $(D
932    compose), but with functions specified in reverse order. This may
933    lead to more readable code in some situation because the order of
934    execution is the same as lexical order.
935 
936    Example:
937 
938 ----
939 // Read an entire text file, split the resulting string in
940 // whitespace-separated tokens, and then convert each token into an
941 // integer
942 int[] a = pipe!(readText, split, map!(to!(int)))("file.txt");
943 ----
944 
945    See_Also: $(LREF compose)
946  */
947 alias pipe(fun...) = compose!(Reverse!(fun));
948 
949 @safe unittest
950 {
951     import std.conv : to;
foo(int a)952     string foo(int a) { return to!(string)(a); }
bar(string a)953     int bar(string a) { return to!(int)(a) + 1; }
baz(int a)954     double baz(int a) { return a + 0.5; }
955     assert(compose!(baz, bar, foo)(1) == 2.5);
956     assert(pipe!(foo, bar, baz)(1) == 2.5);
957 
958     assert(compose!(baz, `to!(int)(a) + 1`, foo)(1) == 2.5);
959     assert(compose!(baz, bar)("1"[]) == 2.5);
960 
961     assert(compose!(baz, bar)("1") == 2.5);
962 
963     assert(compose!(`a + 0.5`, `to!(int)(a) + 1`, foo)(1) == 2.5);
964 }
965 
966 /**
967  * $(LINK2 https://en.wikipedia.org/wiki/Memoization, Memoizes) a function so as
968  * to avoid repeated computation. The memoization structure is a hash table keyed by a
969  * tuple of the function's arguments. There is a speed gain if the
970  * function is repeatedly called with the same arguments and is more
971  * 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).
972 
973 Example:
974 ----
975 double transmogrify(int a, string b)
976 {
977    ... expensive computation ...
978 }
979 alias fastTransmogrify = memoize!transmogrify;
980 unittest
981 {
982     auto slow = transmogrify(2, "hello");
983     auto fast = fastTransmogrify(2, "hello");
984     assert(slow == fast);
985 }
986 ----
987 
988 Technically the memoized function should be pure because $(D memoize) assumes it will
989 always return the same result for a given tuple of arguments. However, $(D memoize) does not
990 enforce that because sometimes it
991 is useful to memoize an impure function, too.
992 */
memoize(alias fun)993 template memoize(alias fun)
994 {
995     import std.traits : ReturnType;
996     // alias Args = Parameters!fun; // Bugzilla 13580
997 
998     ReturnType!fun memoize(Parameters!fun args)
999     {
1000         alias Args = Parameters!fun;
1001         import std.typecons : Tuple;
1002 
1003         static ReturnType!fun[Tuple!Args] memo;
1004         auto t = Tuple!Args(args);
1005         if (auto p = t in memo)
1006             return *p;
1007         return memo[t] = fun(args);
1008     }
1009 }
1010 
1011 /// ditto
memoize(alias fun,uint maxSize)1012 template memoize(alias fun, uint maxSize)
1013 {
1014     import std.traits : ReturnType;
1015     // alias Args = Parameters!fun; // Bugzilla 13580
1016     ReturnType!fun memoize(Parameters!fun args)
1017     {
1018         import std.traits : hasIndirections;
1019         import std.typecons : tuple;
1020         static struct Value { Parameters!fun args; ReturnType!fun res; }
1021         static Value[] memo;
1022         static size_t[] initialized;
1023 
1024         if (!memo.length)
1025         {
1026             import core.memory : GC;
1027 
1028             // Ensure no allocation overflows
1029             static assert(maxSize < size_t.max / Value.sizeof);
1030             static assert(maxSize < size_t.max - (8 * size_t.sizeof - 1));
1031 
1032             enum attr = GC.BlkAttr.NO_INTERIOR | (hasIndirections!Value ? 0 : GC.BlkAttr.NO_SCAN);
1033             memo = (cast(Value*) GC.malloc(Value.sizeof * maxSize, attr))[0 .. maxSize];
1034             enum nwords = (maxSize + 8 * size_t.sizeof - 1) / (8 * size_t.sizeof);
1035             initialized = (cast(size_t*) GC.calloc(nwords * size_t.sizeof, attr | GC.BlkAttr.NO_SCAN))[0 .. nwords];
1036         }
1037 
1038         import core.bitop : bt, bts;
1039         import std.conv : emplace;
1040 
1041         size_t hash;
1042         foreach (ref arg; args)
1043             hash = hashOf(arg, hash);
1044         // cuckoo hashing
1045         immutable idx1 = hash % maxSize;
1046         if (!bt(initialized.ptr, idx1))
1047         {
1048             emplace(&memo[idx1], args, fun(args));
1049             bts(initialized.ptr, idx1); // only set to initialized after setting args and value (bugzilla 14025)
1050             return memo[idx1].res;
1051         }
1052         else if (memo[idx1].args == args)
1053             return memo[idx1].res;
1054         // FNV prime
1055         immutable idx2 = (hash * 16_777_619) % maxSize;
1056         if (!bt(initialized.ptr, idx2))
1057         {
1058             emplace(&memo[idx2], memo[idx1]);
1059             bts(initialized.ptr, idx2); // only set to initialized after setting args and value (bugzilla 14025)
1060         }
1061         else if (memo[idx2].args == args)
1062             return memo[idx2].res;
1063         else if (idx1 != idx2)
1064             memo[idx2] = memo[idx1];
1065 
1066         memo[idx1] = Value(args, fun(args));
1067         return memo[idx1].res;
1068     }
1069 }
1070 
1071 /**
1072  * To _memoize a recursive function, simply insert the memoized call in lieu of the plain recursive call.
1073  * For example, to transform the exponential-time Fibonacci implementation into a linear-time computation:
1074  */
1075 @safe unittest
1076 {
fib(ulong n)1077     ulong fib(ulong n) @safe
1078     {
1079         return n < 2 ? n : memoize!fib(n - 2) + memoize!fib(n - 1);
1080     }
1081     assert(fib(10) == 55);
1082 }
1083 
1084 /**
1085  * To improve the speed of the factorial function,
1086  */
1087 @safe unittest
1088 {
fact(ulong n)1089     ulong fact(ulong n) @safe
1090     {
1091         return n < 2 ? 1 : n * memoize!fact(n - 1);
1092     }
1093     assert(fact(10) == 3628800);
1094 }
1095 
1096 /**
1097  * This memoizes all values of $(D fact) up to the largest argument. To only cache the final
1098  * result, move $(D memoize) outside the function as shown below.
1099  */
1100 @safe unittest
1101 {
factImpl(ulong n)1102     ulong factImpl(ulong n) @safe
1103     {
1104         return n < 2 ? 1 : n * factImpl(n - 1);
1105     }
1106     alias fact = memoize!factImpl;
1107     assert(fact(10) == 3628800);
1108 }
1109 
1110 /**
1111  * When the $(D maxSize) parameter is specified, memoize will used
1112  * a fixed size hash table to limit the number of cached entries.
1113  */
1114 @system unittest // not @safe due to memoize
1115 {
fact(ulong n)1116     ulong fact(ulong n)
1117     {
1118         // Memoize no more than 8 values
1119         return n < 2 ? 1 : n * memoize!(fact, 8)(n - 1);
1120     }
1121     assert(fact(8) == 40320);
1122     // using more entries than maxSize will overwrite existing entries
1123     assert(fact(10) == 3628800);
1124 }
1125 
1126 @system unittest // not @safe due to memoize
1127 {
1128     import core.math : sqrt;
1129     alias msqrt = memoize!(function double(double x) { return sqrt(x); });
1130     auto y = msqrt(2.0);
1131     assert(y == msqrt(2.0));
1132     y = msqrt(4.0);
1133     assert(y == sqrt(4.0));
1134 
1135     // alias mrgb2cmyk = memoize!rgb2cmyk;
1136     // auto z = mrgb2cmyk([43, 56, 76]);
1137     // assert(z == mrgb2cmyk([43, 56, 76]));
1138 
1139     //alias mfib = memoize!fib;
1140 
fib(ulong n)1141     static ulong fib(ulong n) @safe
1142     {
1143         alias mfib = memoize!fib;
1144         return n < 2 ? 1 : mfib(n - 2) + mfib(n - 1);
1145     }
1146 
1147     auto z = fib(10);
1148     assert(z == 89);
1149 
fact(ulong n)1150     static ulong fact(ulong n) @safe
1151     {
1152         alias mfact = memoize!fact;
1153         return n < 2 ? 1 : n * mfact(n - 1);
1154     }
1155     assert(fact(10) == 3628800);
1156 
1157     // Issue 12568
len2(const string s)1158     static uint len2(const string s) { // Error
1159     alias mLen2 = memoize!len2;
1160     if (s.length == 0)
1161         return 0;
1162     else
1163         return 1 + mLen2(s[1 .. $]);
1164     }
1165 
_func(int x)1166     int _func(int x) @safe { return 1; }
1167     alias func = memoize!(_func, 10);
1168     assert(func(int.init) == 1);
1169     assert(func(int.init) == 1);
1170 }
1171 
1172 // 16079: memoize should work with arrays
1173 @safe unittest
1174 {
1175     int executed = 0;
median(T)1176     T median(T)(const T[] nums) {
1177         import std.algorithm.sorting : sort;
1178         executed++;
1179         auto arr = nums.dup;
1180         arr.sort();
1181         if (arr.length % 2)
1182             return arr[$ / 2];
1183         else
1184             return (arr[$ / 2 - 1]
1185                 + arr[$ / 2]) / 2;
1186     }
1187 
1188     alias fastMedian = memoize!(median!int);
1189 
1190     assert(fastMedian([7, 5, 3]) == 5);
1191     assert(fastMedian([7, 5, 3]) == 5);
1192 
1193     assert(executed == 1);
1194 }
1195 
1196 // 16079: memoize should work with structs
1197 @safe unittest
1198 {
1199     int executed = 0;
pickFirst(T)1200     T pickFirst(T)(T first)
1201     {
1202         executed++;
1203         return first;
1204     }
1205 
1206     struct Foo { int k; }
1207     Foo A = Foo(3);
1208 
1209     alias first = memoize!(pickFirst!Foo);
1210     assert(first(Foo(3)) == A);
1211     assert(first(Foo(3)) == A);
1212     assert(executed == 1);
1213 }
1214 
1215 // 16079: memoize should work with classes
1216 @safe unittest
1217 {
1218     int executed = 0;
pickFirst(T)1219     T pickFirst(T)(T first)
1220     {
1221         executed++;
1222         return first;
1223     }
1224 
1225     class Bar
1226     {
1227         size_t k;
this(size_t k)1228         this(size_t k)
1229         {
1230             this.k = k;
1231         }
toHash()1232         override size_t toHash()
1233         {
1234             return k;
1235         }
opEquals(Object o)1236         override bool opEquals(Object o)
1237         {
1238             auto b = cast(Bar) o;
1239             return b && k == b.k;
1240         }
1241     }
1242 
1243     alias firstClass = memoize!(pickFirst!Bar);
1244     assert(firstClass(new Bar(3)).k == 3);
1245     assert(firstClass(new Bar(3)).k == 3);
1246     assert(executed == 1);
1247 }
1248 
DelegateFaker(F)1249 private struct DelegateFaker(F)
1250 {
1251     import std.typecons : FuncInfo, MemberFunctionGenerator;
1252 
1253     // for @safe
1254     static F castToF(THIS)(THIS x) @trusted
1255     {
1256         return cast(F) x;
1257     }
1258 
1259     /*
1260      * What all the stuff below does is this:
1261      *--------------------
1262      * struct DelegateFaker(F) {
1263      *     extern(linkage)
1264      *     [ref] ReturnType!F doIt(Parameters!F args) [@attributes]
1265      *     {
1266      *         auto fp = cast(F) &this;
1267      *         return fp(args);
1268      *     }
1269      * }
1270      *--------------------
1271      */
1272 
1273     // We will use MemberFunctionGenerator in std.typecons.  This is a policy
1274     // configuration for generating the doIt().
1275     template GeneratingPolicy()
1276     {
1277         // Inform the genereator that we only have type information.
1278         enum WITHOUT_SYMBOL = true;
1279 
1280         // Generate the function body of doIt().
1281         template generateFunctionBody(unused...)
1282         {
1283             enum generateFunctionBody =
1284             // [ref] ReturnType doIt(Parameters args) @attributes
1285             q{
1286                 // When this function gets called, the this pointer isn't
1287                 // really a this pointer (no instance even really exists), but
1288                 // a function pointer that points to the function to be called.
1289                 // Cast it to the correct type and call it.
1290 
1291                 auto fp = castToF(&this);
1292                 return fp(args);
1293             };
1294         }
1295     }
1296     // Type information used by the generated code.
1297     alias FuncInfo_doIt = FuncInfo!(F);
1298 
1299     // Generate the member function doIt().
1300     mixin( MemberFunctionGenerator!(GeneratingPolicy!())
1301             .generateFunction!("FuncInfo_doIt", "doIt", F) );
1302 }
1303 
1304 /**
1305  * Convert a callable to a delegate with the same parameter list and
1306  * return type, avoiding heap allocations and use of auxiliary storage.
1307  *
1308  * Example:
1309  * ----
1310  * void doStuff() {
1311  *     writeln("Hello, world.");
1312  * }
1313  *
1314  * void runDelegate(void delegate() myDelegate) {
1315  *     myDelegate();
1316  * }
1317  *
1318  * auto delegateToPass = toDelegate(&doStuff);
1319  * runDelegate(delegateToPass);  // Calls doStuff, prints "Hello, world."
1320  * ----
1321  *
1322  * BUGS:
1323  * $(UL
1324  *   $(LI Does not work with $(D @safe) functions.)
1325  *   $(LI Ignores C-style / D-style variadic arguments.)
1326  * )
1327  */
1328 auto toDelegate(F)(auto ref F fp)
1329 if (isCallable!(F))
1330 {
1331     static if (is(F == delegate))
1332     {
1333         return fp;
1334     }
1335     else static if (is(typeof(&F.opCall) == delegate)
1336                 || (is(typeof(&F.opCall) V : V*) && is(V == function)))
1337     {
1338         return toDelegate(&fp.opCall);
1339     }
1340     else
1341     {
1342         alias DelType = typeof(&(new DelegateFaker!(F)).doIt);
1343 
1344         static struct DelegateFields {
1345             union {
1346                 DelType del;
1347                 //pragma(msg, typeof(del));
1348 
1349                 struct {
1350                     void* contextPtr;
1351                     void* funcPtr;
1352                 }
1353             }
1354         }
1355 
1356         // fp is stored in the returned delegate's context pointer.
1357         // The returned delegate's function pointer points to
1358         // DelegateFaker.doIt.
1359         DelegateFields df;
1360 
1361         df.contextPtr = cast(void*) fp;
1362 
1363         DelegateFaker!(F) dummy;
1364         auto dummyDel = &dummy.doIt;
1365         df.funcPtr = dummyDel.funcptr;
1366 
1367         return df.del;
1368     }
1369 }
1370 
1371 ///
1372 @system unittest
1373 {
1374     static int inc(ref uint num) {
1375         num++;
1376         return 8675309;
1377     }
1378 
1379     uint myNum = 0;
1380     auto incMyNumDel = toDelegate(&inc);
1381     auto returnVal = incMyNumDel(myNum);
1382     assert(myNum == 1);
1383 }
1384 
1385 @system unittest // not @safe due to toDelegate
1386 {
1387     static int inc(ref uint num) {
1388         num++;
1389         return 8675309;
1390     }
1391 
1392     uint myNum = 0;
1393     auto incMyNumDel = toDelegate(&inc);
1394     int delegate(ref uint) dg = incMyNumDel;
1395     auto returnVal = incMyNumDel(myNum);
1396     assert(myNum == 1);
1397 
1398     interface I { int opCall(); }
1399     class C: I { int opCall() { inc(myNum); return myNum;} }
1400     auto c = new C;
1401     auto i = cast(I) c;
1402 
1403     auto getvalc = toDelegate(c);
1404     assert(getvalc() == 2);
1405 
1406     auto getvali = toDelegate(i);
1407     assert(getvali() == 3);
1408 
1409     struct S1 { int opCall() { inc(myNum); return myNum; } }
1410     static assert(!is(typeof(&s1.opCall) == delegate));
1411     S1 s1;
1412     auto getvals1 = toDelegate(s1);
1413     assert(getvals1() == 4);
1414 
1415     struct S2 { static int opCall() { return 123456; } }
1416     static assert(!is(typeof(&S2.opCall) == delegate));
1417     S2 s2;
1418     auto getvals2 =&S2.opCall;
1419     assert(getvals2() == 123456);
1420 
1421     /* test for attributes */
1422     {
1423         static int refvar = 0xDeadFace;
1424 
1425         static ref int func_ref() { return refvar; }
1426         static int func_pure() pure { return 1; }
1427         static int func_nothrow() nothrow { return 2; }
1428         static int func_property() @property { return 3; }
1429         static int func_safe() @safe { return 4; }
1430         static int func_trusted() @trusted { return 5; }
1431         static int func_system() @system { return 6; }
1432         static int func_pure_nothrow() pure nothrow { return 7; }
1433         static int func_pure_nothrow_safe() pure nothrow @safe { return 8; }
1434 
1435         auto dg_ref = toDelegate(&func_ref);
1436         int delegate() pure dg_pure = toDelegate(&func_pure);
1437         int delegate() nothrow dg_nothrow = toDelegate(&func_nothrow);
1438         int delegate() @property dg_property = toDelegate(&func_property);
1439         int delegate() @safe dg_safe = toDelegate(&func_safe);
1440         int delegate() @trusted dg_trusted = toDelegate(&func_trusted);
1441         int delegate() @system dg_system = toDelegate(&func_system);
1442         int delegate() pure nothrow dg_pure_nothrow = toDelegate(&func_pure_nothrow);
1443         int delegate() @safe pure nothrow dg_pure_nothrow_safe = toDelegate(&func_pure_nothrow_safe);
1444 
1445         //static assert(is(typeof(dg_ref) == ref int delegate())); // [BUG@DMD]
1446 
1447         assert(dg_ref() == refvar);
1448         assert(dg_pure() == 1);
1449         assert(dg_nothrow() == 2);
1450         assert(dg_property() == 3);
1451         assert(dg_safe() == 4);
1452         assert(dg_trusted() == 5);
1453         assert(dg_system() == 6);
1454         assert(dg_pure_nothrow() == 7);
1455         assert(dg_pure_nothrow_safe() == 8);
1456     }
1457     /* test for linkage */
1458     {
1459         struct S
1460         {
1461             extern(C) static void xtrnC() {}
1462             extern(D) static void xtrnD() {}
1463         }
1464         auto dg_xtrnC = toDelegate(&S.xtrnC);
1465         auto dg_xtrnD = toDelegate(&S.xtrnD);
1466         static assert(! is(typeof(dg_xtrnC) == typeof(dg_xtrnD)));
1467     }
1468 }
1469 
1470 /**
1471 Forwards function arguments with saving ref-ness.
1472 */
1473 template forward(args...)
1474 {
1475     static if (args.length)
1476     {
1477         import std.algorithm.mutation : move;
1478 
1479         alias arg = args[0];
1480         static if (__traits(isRef, arg))
1481             alias fwd = arg;
1482         else
1483             @property fwd()(){ return move(arg); }
1484         alias forward = AliasSeq!(fwd, forward!(args[1..$]));
1485     }
1486     else
1487         alias forward = AliasSeq!();
1488 }
1489 
1490 ///
1491 @safe unittest
1492 {
1493     class C
1494     {
1495         static int foo(int n) { return 1; }
1496         static int foo(ref int n) { return 2; }
1497     }
1498     int bar()(auto ref int x) { return C.foo(forward!x); }
1499 
1500     assert(bar(1) == 1);
1501     int i;
1502     assert(bar(i) == 2);
1503 }
1504 
1505 ///
1506 @safe unittest
1507 {
1508     void foo(int n, ref string s) { s = null; foreach (i; 0 .. n) s ~= "Hello"; }
1509 
1510     // forwards all arguments which are bound to parameter tuple
1511     void bar(Args...)(auto ref Args args) { return foo(forward!args); }
1512 
1513     // forwards all arguments with swapping order
1514     void baz(Args...)(auto ref Args args) { return foo(forward!args[$/2..$], forward!args[0..$/2]); }
1515 
1516     string s;
1517     bar(1, s);
1518     assert(s == "Hello");
1519     baz(s, 2);
1520     assert(s == "HelloHello");
1521 }
1522 
1523 @safe unittest
1524 {
1525     auto foo(TL...)(auto ref TL args)
1526     {
1527         string result = "";
1528         foreach (i, _; args)
1529         {
1530             //pragma(msg, "[",i,"] ", __traits(isRef, args[i]) ? "L" : "R");
1531             result ~= __traits(isRef, args[i]) ? "L" : "R";
1532         }
1533         return result;
1534     }
1535 
1536     string bar(TL...)(auto ref TL args)
1537     {
1538         return foo(forward!args);
1539     }
1540     string baz(TL...)(auto ref TL args)
1541     {
1542         int x;
1543         return foo(forward!args[3], forward!args[2], 1, forward!args[1], forward!args[0], x);
1544     }
1545 
1546     struct S {}
1547     S makeS(){ return S(); }
1548     int n;
1549     string s;
1550     assert(bar(S(), makeS(), n, s) == "RRLL");
1551     assert(baz(S(), makeS(), n, s) == "LLRRRL");
1552 }
1553 
1554 @safe unittest
1555 {
1556     ref int foo(return ref int a) { return a; }
1557     ref int bar(Args)(auto ref Args args)
1558     {
1559         return foo(forward!args);
1560     }
1561     static assert(!__traits(compiles, { auto x1 = bar(3); })); // case of NG
1562     int value = 3;
1563     auto x2 = bar(value); // case of OK
1564 }
1565