1// Written in the D programming language.
2
3/**
4Functions that manipulate other functions.
5
6This module provides functions for compile time function composition. These
7functions 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
51Copyright: Copyright Andrei Alexandrescu 2008 - 2009.
52License:   $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
53Authors:   $(HTTP erdani.org, Andrei Alexandrescu)
54Source:    $(PHOBOSSRC std/_functional.d)
55*/
56/*
57         Copyright Andrei Alexandrescu 2008 - 2009.
58Distributed 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*/
62module std.functional;
63
64import std.meta; // AliasSeq, Reverse
65import std.traits; // isCallable, Parameters
66
67
68private 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/**
96Transforms a string representing an expression into a unary
97function. The string must either use symbol name $(D a) as
98the parameter or provide the symbol via the $(D parmName) argument.
99If $(D fun) is not a string, $(D unaryFun) aliases itself away to $(D fun).
100*/
101
102template 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        }
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{
138    static int f1(int a) { return a + 1; }
139    static assert(is(typeof(unaryFun!(f1)(1)) == int));
140    assert(unaryFun!(f1)(41) == 42);
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    {
153        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    {
166        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/**
179Transforms a string representing an expression into a binary function. The
180string must either use symbol names $(D a) and $(D b) as the parameters or
181provide the symbols via the $(D parm1Name) and $(D parm2Name) arguments.
182If $(D fun) is not a string, $(D binaryFun) aliases itself away to
183$(D fun).
184*/
185
186template 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        }
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{
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);
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    {
239        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    {
246        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 '.'.
259private 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
276private 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
293private 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
305private 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
352private 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
420template safeOp(string S)
421if (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
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;
470        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*/
482alias lessThan = safeOp!"<";
483
484///
485pure @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*/
503alias 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*/
524alias 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*/
537template 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;
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{
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{
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{
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*/
587template 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;
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/**
615Negates predicate $(D pred).
616 */
617template 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
655applies) $(D_PARAM fun) by tying its first argument to $(D_PARAM arg).
656 */
657template 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{
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{
706    static int f1(int a, int b) { return a + b; }
707    assert(partial!(f1, 5)(6) == 11);
708
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
720    static int funOneArg(int a) { return a; }
721    assert(partial!(funOneArg, 1)() == 1);
722
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{
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    {
756        static string opCall(string a, string b) { return a ~ b; }
757        int opCall(int a, int b) { return a * b; }
758        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    {
767        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
776    static A funOneArg(A)(A a) { return a; }
777    alias funOneArg1 = partial!(funOneArg, 1);
778    assert(funOneArg1() == 1);
779
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/**
790Takes multiple functions and adjoins them together. The result is a
791$(REF Tuple, std,typecons) with one element per passed-in function. Upon
792invocation, the returned tuple is the adjoined results of all
793functions.
794
795Note: 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*/
799template adjoin(F...)
800if (F.length == 1)
801{
802    alias adjoin = F[0];
803}
804/// ditto
805template adjoin(F...)
806if (F.length > 1)
807{
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;
832    static bool f1(int a) { return a != 0; }
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;
842    static bool F1(int a) { return a != 0; }
843    auto x1 = adjoin!(F1)(5);
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
852    bool F4(int a) { return a != x1; }
853    alias eff4 = adjoin!(F4);
854    static struct S
855    {
856        bool delegate(int) @safe store;
857        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);
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);
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*/
892template 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
942int[] a = pipe!(readText, split, map!(to!(int)))("file.txt");
943----
944
945   See_Also: $(LREF compose)
946 */
947alias pipe(fun...) = compose!(Reverse!(fun));
948
949@safe unittest
950{
951    import std.conv : to;
952    string foo(int a) { return to!(string)(a); }
953    int bar(string a) { return to!(int)(a) + 1; }
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
973Example:
974----
975double transmogrify(int a, string b)
976{
977   ... expensive computation ...
978}
979alias fastTransmogrify = memoize!transmogrify;
980unittest
981{
982    auto slow = transmogrify(2, "hello");
983    auto fast = fastTransmogrify(2, "hello");
984    assert(slow == fast);
985}
986----
987
988Technically the memoized function should be pure because $(D memoize) assumes it will
989always return the same result for a given tuple of arguments. However, $(D memoize) does not
990enforce that because sometimes it
991is useful to memoize an impure function, too.
992*/
993template 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
1012template 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{
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{
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{
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{
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
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
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
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
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;
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;
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;
1219    T pickFirst(T)(T first)
1220    {
1221        executed++;
1222        return first;
1223    }
1224
1225    class Bar
1226    {
1227        size_t k;
1228        this(size_t k)
1229        {
1230            this.k = k;
1231        }
1232        override size_t toHash()
1233        {
1234            return k;
1235        }
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
1249private 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 */
1328auto toDelegate(F)(auto ref F fp)
1329if (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/**
1471Forwards function arguments with saving ref-ness.
1472*/
1473template 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