Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

root/trunk/dranges/functional.d

Revision 108, 54.6 kB (checked in by Philippe Sigaud, 14 years ago)

Code cleaning: bugs in docs found while generating the complete documentation.

Line 
1 // Written in the D programming language
2
3 /**
4 This module contains all the function-related templates.
5 Its main use used to be to generate functions from strings, with the $(M naryFun) template,
6 an extension of $(M std.functional.unaryFun) and $(M binaryFun). Now, it presents a nice collection
7 of adaptors and transformers: functions or templates acting on functions to transform them.
8
9 License:   <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
10 Authors:   Philippe Sigaud
11
12 Distributed under the Boost Software License, Version 1.0.
13 (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
14 */
15 module dranges.functional;
16
17 import std.algorithm,
18        std.array,
19        std.bigint,
20        std.conv,
21        std.exception,
22        std.functional,
23        std.math,
24        std.metastrings,
25        std.range,
26        std.stdio,
27        std.string,
28        std.traits,
29        std.typecons,
30        std.typetuple;
31
32 import dranges.algorithm,
33        dranges.patternmatch,
34        dranges.predicate,
35        dranges.range,
36        dranges.templates,
37        dranges.traits,
38        dranges.tuple,
39        dranges.typetuple;
40 /**
41 Gives the _arity of a function: unary, binary, etc. A 0-args function has an _arity of 0.
42
43 ----
44 int foo0() { return 0;}
45 int foo1(int a) { return a;}
46 int foo2(int a, int b) { return a+b;}
47
48 assert(arity!foo0 == 0);
49 assert(arity!foo1 == 1);
50 assert(arity!foo2 == 2);
51 ----
52
53 It does not work on non-instantiated template functions (because they
54 are not functions) and gives an _arity of 1 for variadic functions, because
55 their variadic list is considered as one arg.
56 ----
57 T foo(T)(T t) { ...};
58 auto a = arity!foo; // error !
59 auto b = arity!(foo!int); // OK.
60 //
61 int foov(int a...) { return 0;}
62 assert(arity!foov == 1);
63 ----
64
65 See_Also: $(M dranges.templates.TemplateFunArity).
66 */
67 template arity(alias fun) if (isFunction!fun) {
68     enum size_t arity = ParameterTypeTuple!(fun).length;
69 }
70
71 template arity(string fun)
72 {
73     alias aritySImpl!(" " ~ fun ~ " ",0).result arity;
74 }
75
76 unittest {
77     int foo0() { return 0;}
78     int foo1(int a) { return a;}
79     int foo2(int a, int b) { return a+b;}
80     T foo3(T, U)(T t, T tt, U u) { return t;} // templated
81     assert(arity!foo0 == 0);
82     assert(arity!foo1 == 1);
83     assert(arity!foo2 == 2);
84     assert(!__traits(compiles, arity!foo3)); // does not work on non-instantiated functions
85     assert(arity!(foo3!(int,double)) == 3);  // foo3!(int, double) is a 3-args function
86
87     int foov(int a...) { return 0;}
88     assert(arity!foov == 1);
89 }
90
91 /// Given a bunch of functions names, gives the typetuple of their return types. Used by $(M juxtapose).
92 template ReturnTypes(Funs...)
93 {
94     alias MapOnAlias!(ReturnType, Funs) ReturnTypes;
95 }
96
97 /// Given a bunch of functions names, gives the (flattened) typetuple of their return values. Used by $(M juxtapose).
98 template ParameterTypeTuples(alias fun, Rest...)
99 {
100     alias MapOnAlias!(ParameterTypeTuple, fun, Rest) ParameterTypeTuples;
101 }
102
103 template SumOfArity(size_t zero, alias fun)
104 {
105     enum size_t SumOfArity = zero + arity!fun;
106 }
107
108 template SumOfArities(F...)
109 {
110     alias StaticScan!(SumOfArity, 0, F) SumOfArities;
111 }
112
113 template SumOfReturn(size_t zero, alias fun)
114 {
115     static if (is(ReturnType!fun == void))
116         enum size_t SumOfReturn = zero;
117     else
118         enum size_t SumOfReturn = zero + 1;
119 }
120
121 template SumOfReturns(Funs...)
122 {
123     alias StaticScan!(SumOfReturn, 0, Funs) SumOfReturns;
124 }
125
126
127 /**
128 Takes n functions and create a new one, taking as arguments the concatenation of all input functions
129 arguments and returning a tuple of their results. It will deal correctly with nullary (0-arg) functions
130 by inserting their return value at the right place and with void-returning functions.
131 Do not use variadic functions, though.
132
133 This template is very useful when dealing with tuple-returning ranges.
134
135 Example:
136 ----
137 int foo(int i) { return i*i;}       // int -> int
138 int bar() { return 0;}              // ()  -> int
139 void baz(string s) {}               // string -> ()
140 double[] quux(double d, double[] f) // (double,double[]) -> double[]
141     { return f ~ d;}
142
143 alias juxtapose!(foo,bar,baz,quux) jux; // jux takes (int,string, double, double[]), returns Tuple!(int,int,double[]);
144
145 auto ir = [0,1,2,3,4,5];
146 auto sr = ["abc", "def","ghijk"];
147 auto dr = [3.14,2.78,1.00,-1.414];
148 auto fr = [[0.1,0.2], [0.0,-1.0,-2.0]];
149
150 auto m = tmap!jux(ir,sr,dr,fr);
151 ----
152
153 Note: another, more mathematical way, to look at it is that $(M _juxtapose) creates a function whose type is the product the input functions' types.
154 In D, product of types are tuples.
155 */
156 template juxtapose(Funs...)
157 {
158     Tuple!(StaticFilter!(isNotVoid, ReturnTypes!Funs)) juxtapose(ParameterTypeTuples!Funs params) {
159         typeof(return) result;
160         alias SumOfArities!Funs arities;
161         alias SumOfReturns!Funs returns;
162         foreach(i, Fun; Funs) {
163             enum firstParam = arities[i];
164             enum lastParam = firstParam + arity!(Fun);
165             static if (returns[i] != returns[i+1])
166                 result.field[returns[i]] = Fun(params[firstParam..lastParam]);
167         }
168         return result;
169     }
170 }
171
172 unittest
173 {
174     int foo(int i) { return i*i;}       // int -> int
175     int bar() { return 0;}              // ()  -> int
176     void baz(string s) {}               // string -> ()
177     double[] quux(double d, double[] f) // (double,double[]) -> double[]
178         { return f ~ d;}
179
180     alias juxtapose!(foo,bar,baz,quux) jux; // jux takes (int,string, double, double[]), returns Tuple!(int,int,double[]);
181
182     auto ir = [0,1,2,3,4,5];
183     auto sr = ["abc", "def","ghijk"];
184     auto dr = [3.14,2.78,1.00,-1.414];
185     auto fr = [[0.1,0.2], [0.0,-1.0,-2.0]];
186
187     auto m = tmap!jux(ir,sr,dr,fr);
188 }
189 /+
190 template juxtapose2(F...)
191 {
192     Tuple!(ReturnTypes!F) juxtapose2(Tuple!(ParameterTypeTuples!F) params) {
193         typeof(return) result;
194         alias SumOfArities!F arities;
195         foreach(i, Unused; F) {
196             enum firstParam = arities[i];
197             enum lastParam = firstParam + arity!(F[i]);
198             result.field[i] = F[i](params.expand[firstParam..lastParam]);
199         }
200         return result;
201     }
202 }
203 +/
204
205 template isNotVoid(T)
206 {
207     enum bool isNotVoid = !is(T == void);
208 }
209
210 struct FlipnR(alias fun)
211 {
212     size_t n;
213     typeof(fun(R.init, 0)) opCall(R)(R r) if (isForwardRange!R)// && is(typeof(fun(r,n))))
214     {
215         return fun(r,n);
216     }
217 }
218
219 /**
220 Flip and curry range functions, like $(M take), $(M drop), etc. These take a range and a size_t arguments, like $(M take(r,3)), etc.
221 But sometimes, you just want to create a curried function that will act on any range.
222
223 Example:
224 ----
225 alias flipn!take takeN; // takeN is a generic function, waiting for a number of elements to take.
226 auto take3 = takeN(3);  // take3 is a generic function, taking 3 elements on any range (returns take(range,3))
227
228 auto threes = map!take3([[0,1,2,3,4,5],[6,7,8,9], [10]]); // get the first three elements of each range
229 auto witness =          [[0,1,2],      [6,7,8],   [10]];
230 foreach(i, elem; witness)  {assert(equal(elem, threes.front)); threes.popFront;}
231 ----
232 */
233 FlipnR!fun flipn(alias fun)(size_t n)
234 {
235     FlipnR!(fun) tnr;
236     tnr.n = n;
237     return tnr;
238 }
239
240 unittest
241 {
242     auto rr = [[0,1,2,3,4,5],[6,7,8,9], [10]];
243
244     alias flipn!take takeN; // takeN is a higher-order function, waiting for a number of elements to take.
245     auto take3 = takeN(3);  // take3 is a generic function, taking 3 elements on any range (returns take(range,3))
246
247     auto threes = map!take3(rr); // get the first three elements of each range
248     auto witness = [[0,1,2],[6,7,8],[10]];
249     foreach(elem; witness)
250     {
251         assert(equal(elem, threes.front));
252         threes.popFront;
253     }
254
255     auto take0 = takeN(0);
256     auto zeroes = map!take0(rr);
257     foreach(elem; zeroes) assert(elem.empty);
258
259     auto take100 = takeN(100);
260     auto all = map!take100(rr);
261     foreach(elem; rr) {assert(equal(elem, all.front)); all.popFront;}
262 }
263
264
265 /**
266 Flips (reverses) the arguments of a function. It also works for template functions, even
267 variadic ones. Do not use it on standard variadic functions, though.
268
269 Example:
270 ----
271 int sub(int i, int j) { return i-j;}
272 int one(int i) { return i;}
273 double three(double a, int b, string c) { return a;}
274
275 alias flip!sub fsub;
276 alias flip!one fone;
277 alias flip!three fthree;
278
279 assert(fsub(1,2) == sub(2,1));
280 assert(fone(1) == one(1));
281 assert(fthree("abc", 0, 3.14) == three(3.14, 0, "abc"));
282
283 string conj(A,B)(A a, B b)
284 {
285     return to!string(a)~to!string(b);
286 }
287
288 string conjAll(A...)(A a) // variadic template function
289 {
290     string result;
291     foreach(i,elem;a) result ~= to!string(elem);
292     return result;
293 }
294
295 alias flip!conj fconj;
296 alias flip!conjAll fconjAll;
297
298 assert(fconj(1,2) == "21");
299 assert(fconjAll(1,2,3,4) == "4321");
300 ----
301 */
302 template flip(alias fun)
303 {
304     static if (isFunctionType!(typeof(fun)))
305         ReturnType!fun flip(ReverseTypes!(ParameterTypeTuple!fun) rargs)
306         {
307             return fun(reverseTuple(tuple(rargs)).expand);
308         }
309     else
310         typeof(fun(Init!(ReverseTypes!T))) flip(T...)(T rargs)
311         {
312             return fun(reverseTuple(tuple(rargs)).expand);
313         }
314 }
315
316 version(unittest)
317 {
318     string conj(A,B)(A a, B b)
319     {
320         return to!string(a)~to!string(b);
321     }
322
323     string conjAll(A...)(A a)
324     {
325         string result;
326         foreach(i,elem;a) result ~= to!string(elem);
327         return result;
328     }
329 }
330
331 unittest
332 {
333     int sub(int i, int j) { return i-j;}
334     int one(int i) { return i;}
335     int none() { return 0;}
336     double three(double a, int b, string c) { return a;}
337
338     alias flip!sub fsub;
339     alias flip!one fone;
340     alias flip!none fnone;
341     alias flip!three fthree;
342
343     assert(fsub(1,2) == sub(2,1));
344     assert(fone(1) == one(1));
345     assert(fnone() == none());
346     assert(fthree("abc", 0, 3.14) == three(3.14, 0, "abc"));
347
348     alias flip!conj fconj;
349     alias flip!conjAll fconjAll;
350
351     assert(fconj(1,2) == "21");
352     assert(fconjAll(1,2,3,4) == "4321");
353 }
354
355 /**
356 Takes a D function, and curries it (in the Haskell sense, not as Phobos' $(M std.functional._curry)): given
357 a n-args function, it creates n 1-arg functions nested inside one another. When
358 all original arguments are reached, it returns the result. It's useful to make 'incomplete'
359 functions to be completed by ranges elements.
360
361 Example:
362 ----
363 int add(int i, int j) { return i+j;}
364 alias curry!add cadd; // cadd waits for an int, will return an int delegate(int)
365 auto add3 = cadd(3); // add3 is a function that take an int and return this int + 3.
366
367 auto m = map!add3([0,1,2,3]);
368 assert(equal(m, [3,4,5,6]));
369
370 bool equals(int i, int j) { return i==j;}
371 alias curry!equals cequals;
372 auto equals4 = cequals(4); // equals4 is a function taking an int and return true iff this int is 4.
373 auto f = filter!equals4([2,3,4,5,4,3,2,2,3,4]);
374 assert(equal(f, [4,4,4]));
375 ----
376
377 What's fun is that it'll work for template functions too.
378
379 Example:
380 ----
381 string conj(A, B)(A a, B b)
382 {
383     return to!string(a)~to!string(b);
384 }
385
386 alias curry!conj cconj;
387 auto c1 = cconj(1); // c1 is a template function waiting for any type.
388 assert(c1('a') == "1a");
389 ----
390 BUG:
391 for now, it does not verify the compatibility of types while you give it the arguments. It's only
392 at the end that it sees whether or not it can call the function with these arguments.
393 Example:
394 ----
395 // given a function like this, with dependencies between the arguments' types:
396 A foo(A,B,C)(A a, Tuple!(B,A) b, Tuple!(C,B,A) c) { return a+b.field[1]+c.field[2];}
397 // if you curries it and gives it an int as first argument, the returned template function should really be:
398 int foo2(B,C)(Tuple!(B,int) b) { return anotherFunction;}
399 // because we now know A to be an int...
400 ----
401 */
402 template curry(alias fun)
403 {
404     static if (isFunction!fun)
405         enum curry =  mixin(curryImpl!(fun, "", ParameterTypeTuple!fun));
406     else // template function
407         enum curry = curriedFunction!(fun)();
408 }
409
410 template curryImpl(alias fun, string xs, T...)
411 {
412     static if (T.length == 0)
413         enum curryImpl = "&fun";
414     else static if (T.length == 1)
415         enum curryImpl = "(" ~ T[0].stringof  ~ " x1) { return fun(" ~ xs ~ "x1);}";
416     else
417         enum curryImpl = "(" ~ T[0].stringof  ~ " x" ~ to!string(T.length) ~ ") { return "
418                             ~ curryImpl!(fun,xs ~ "x" ~ to!string(T.length) ~ ", ", T[1..$]) ~ ";}";
419 }
420
421 struct CurriedFunction(alias fun, T...) /+if (T.length)+/
422 {
423     T _t;
424     static if (T.length)
425         void initialize(T t) { _t = t;}
426
427     template OpCallType(U...)
428     {
429         static if (is (typeof(fun(Init!T, Init!U))))
430             alias typeof(fun(Init!T, Init!U)) OpCallType;
431         else
432             alias CurriedFunction!(fun, T, U) OpCallType;
433     }
434
435     OpCallType!U opCall(U...)(U u)
436     {
437         static if(is(typeof(fun(_t, u))))
438             return fun(_t,u);
439         else
440         {
441             CurriedFunction!(fun, T, U) cf;
442             static if (U.length) cf.initialize(_t, u);
443             return cf;
444         }
445     }
446 }
447
448 CurriedFunction!(fun, TypeTuple!()) curriedFunction(alias fun)()
449 {
450     CurriedFunction!(fun, TypeTuple!()) cf;
451     return cf;
452 }
453
454 unittest
455 {
456     int add(int i, int j) { return i+j;}
457     alias curry!add cadd; // cadd waits for an int, will return an int delegate(int)
458     auto add3 = cadd(3); // add3 is a function that take an int and return this int + 3.
459
460     auto m = map!add3([0,1,2,3]);
461     assert(equal(m, [3,4,5,6]));
462
463     bool equals(int i, int j) { return i==j;}
464     alias curry!equals cequals;
465     auto equals4 = cequals(4); // equals4 is a function taking an int and return true iff this int is 4.
466     auto f = filter!equals4([2,3,4,5,4,3,2,2,3,4]);
467     assert(equal(f, [4,4,4]));
468 }
469
470 struct InvertibleFun(A, B)
471 {
472     B delegate(A) fun;
473     A delegate(B) funInv;
474
475     AB!(A,B,T) opCall(T)(T t) if (is(T == A) || is(T == B))
476     {
477         static if (is(T == A))
478             return fun(t);
479         else
480             return funInv(t);
481     }
482 }
483
484 /**
485 Takes two delegates: one from $(M A) to $(M B), the other from $(M B) to $(M A). $(M A) and $(M B) must be different types.
486 The functions are supposed to be the inverse of one another (that is: f(g(x)) == x), but that's not checked.
487 $(M _invertibleFun) is then a function that accepts either a $(M A) or a $(M B) and then returns a $(M B) or a $(M A).
488 */
489 InvertibleFun!(A,B) invertibleFun(A, B)(B delegate(A) fun, A delegate(B) funInv)
490 {
491     InvertibleFun!(A,B) ifun;
492     ifun.fun = fun;
493     ifun.funInv = funInv;
494     return ifun;
495 }
496
497 struct Apply(T...)
498 {
499     T value;
500
501     typeof(F.init(Init!T)) opCall(F)(F fun)
502     {
503         return fun(value);
504     }
505 }
506
507 /**
508 Takes a value argument and creates a function (in fact, a struct with an opCall) that will accept any delegate
509 and _apply it to the original value. It's useful when you want to map a certain value on a range of functions:
510 just map $(M _apply!value) to the range.
511
512 Example:
513 ----
514 int f0(int i) { return i;}
515 int f1(int i) { return i*i;}
516 int f2(int i) { return i*i*i;}
517
518 auto apply4 = apply(4); // will call any function with '4' as argument.
519 auto rangeFun = [&f0, &f1, &f2];
520 auto map4 = map!apply4(rangeFun);
521 assert(equal(map4, [4, 4*4, 4*4*4]));
522
523 // This works for n-args functions too:
524 double g0(int i, double d) { return i+d;}
525
526 auto apply123 = apply(1, 2.30);
527 assert(apply123(&g0) == 3.30);
528 ----
529 */
530 Apply!T apply(T...)(T value)
531 {
532     Apply!T app;
533     foreach(i, Type; T) app.value[i] = value[i];
534     return app;
535 }
536
537 unittest
538 {
539     int f0(int i) { return i;}
540     int f1(int i) { return i*i;}
541     int f2(int i) { return i*i*i;}
542
543     auto apply4 = apply(4); // will call any function with '4' as argument.
544     auto rangeFun = [&f0, &f1, &f2];
545     auto map4 = map!apply4(rangeFun);
546     assert(equal(map4, [4, 4*4, 4*4*4]));
547
548     // This works for n-args functions too:
549     double g0(int i, double d) { return i+d;}
550
551     auto apply123 = apply(1, 2.30);
552     assert(apply123(&g0) == 3.30);
553 }
554
555 /**
556 Transforms a standard function into a destructuring one. Given:
557 ----
558 int foo(int a, int b, int c) {}
559 ----
560 then, $(M _destructured!foo) is a function that accepts three $(M int)s as arguments, but also $(M Tuple!(int,int,int))
561 or $(M int[]) or $(M int[3]) or even any class $(M C) or struct $(M S) if $(M C.tupleof)/$(M S.tupleof) gives three $(M int)s. In effect,
562 $(M _destructured!foo) will try to destructure (decompose, crack open, if you will) anything passed to it, to find three $(M int)s in a row to give
563 to $(M foo).
564
565 Note: It's still 'in construction', as it depends on the $(M __()) function from $(M dranges.reftuple). The doc
566 should be extended.
567 TODO: also if t is itself a tuple __(params) = t;
568 */
569 template destructured(alias fun)
570 {
571     ReturnType!fun destructured(T...)(T t)
572         if(__traits(compiles, {
573                                 ParameterTypeTuple!fun params;
574                                 _(params) = tuple(t);
575                                 return fun(params);
576                               }))
577     {
578         ParameterTypeTuple!fun params;
579         _(params) = tuple(t);
580         return fun(params);
581     }
582 }
583
584 /**
585 Transforms a function $(M foo) taking a $(M T) into a function accepting a $(M T[]) as an argument
586 and which applies $(M foo) to each element of the array, returning the resulting array.
587
588 Example:
589 ----
590 int foo(int i) { return i*i;}
591 alias mapper!foo mfoo;
592
593 assert(mfoo([0,1,2,3,4]) == [0,1,4,9,16]);
594 ----
595
596 If $(M foo) takes more than one argument, $(M _mapper!foo) waits for a $(M Tuple!(Args)[]) or accepts
597 a variadic number of arguments, as long as the types and their numbers correspond.
598
599 Example:
600 ----
601 int bar(int i, double j, string s) { return (to!int(i*j));}
602 alias mapper!bar mbar;
603
604 assert(mbar(1,3.14,"ab", 2,-0.5,"hello!", 0,0,"") == [3,-3,0]);
605 ----
606 TODO: expand tuples [tuple(a,b), tuple(a,b), ...]
607 */
608 template mapper(alias fun)
609 {
610     auto mapper(T...)(T args) {
611         static if (T.length >1 || (T.length == 1 && !isDynamicArray!(T[0]))) // args as tuple
612         {
613             static if (is(ParameterTypeTuple!fun)
614                        && (ParameterTypeTuple!fun).length > 1
615                        && T.length % (ParameterTypeTuple!fun).length == 0) // more than one param
616             {
617                 enum nargs = (ParameterTypeTuple!fun).length;
618                 ReturnType!fun[] result = new ReturnType!fun[T.length / nargs];
619                 foreach(i, Arg; T) {
620                     static if (i % nargs == 0) result[i/nargs] = fun(args[i..i+nargs]);
621                 }
622                 return result;
623             }
624             else // one param or we cannot determine it (template function, for example)
625             {
626                 alias typeof(fun(CommonType!T.init)) RT;
627                 RT[] result = new RT[args.length];
628                 foreach(i,Arg; T) result[i] = fun(args[i]);
629                 return result;
630             }
631         }
632         else    // args as array
633         {
634             alias typeof(fun(T[0][0].init)) RT;
635             RT[] result = new RT[args[0].length];
636             foreach(i,arg; args[0]) result[i] = fun(arg);
637             return result;
638         }
639     }
640 }
641
642 unittest
643 {
644     int foo(int i) { return i*i;}
645     alias mapper!foo mfoo;
646
647     assert(mfoo([0,1,2,3,4]) == [0,1,4,9,16]);
648
649     int bar(int i, double j, string s) { return (to!int(i*j));}
650     alias mapper!bar mbar;
651
652     assert(mbar(1,3.14,"ab", 2,-1.5,"hello!", 0,0,"") == [3,-3,0]);
653 }
654
655 /**
656 Transforms a function $(M foo) accepting a $(M T) into a function accepting
657 a $(M Tuple!(T,T,T,...T)) (or any tuple with compatible types). It will apply
658 $(M foo) to all elements of the tuple and return the tuple of these results.
659
660 Example:
661 ----
662 int foo(int i) { return i*i;}
663 alias tupler!foo tfoo;
664 auto t = tuple(0,1,2,3,4);
665
666 assert(tfoo(t) == tuple(0,1,4,9,16));
667 ----
668 */
669 template tupler(alias fun)
670 {
671     auto tupler(T)(T tup) if (is(typeof(fun(CommonType!(T.Types).init))))
672     {
673         alias typeof(fun(CommonType!(T.Types).init)) RT;
674         alias TypeNuple!(RT, T.Types.length) TRT;
675         TRT result;
676         foreach(i, Type; TRT) result[i] = fun(tup.field[i]);
677         return tuple(result);
678     }
679 }
680
681 unittest
682 {
683     int foo(int i) { return i*i;}
684     alias tupler!foo tfoo;
685     auto t = tuple(0,1,2,3,4);
686
687     assert(tfoo(t) == tuple(0,1,4,9,16));
688 }
689
690 /// The void function: takes any arguments, returns $(M void).
691 void voidFun(...) {}
692
693 /// The _null function: takes no argument, returns $(M void).
694 void nullFun() {}
695
696 /**
697 Takes any value, returns a constant function: one that accepts any arguments and will always return
698 the initial value. If called with no argument, it will produce the equivalent of $(M voidFun).
699
700 Example:
701 ----
702 auto one = constantFun(1);
703 assert(equal(map!one(["a","b","abc"]), [1,1,1]));
704 ----
705 */
706 T[0] delegate(...) constantFun(T...)(T t) if (T.length == 1)
707 {
708     return (...) { return t[0];};
709 }
710
711 /// ditto
712 Tuple!T delegate(...) constantFun(T...)(T t) if (T.length > 1)
713 {
714     return (...) { return tuple(t);};
715 }
716 /// ditto
717 void delegate(...) constantFun(T...)(T t) if (T.length == 0)
718 {
719     return (...) { return;};
720 }
721
722 unittest
723 {
724     auto one = constantFun(1);
725     assert(equal(map!one(["a","b","abc"]), [1,1,1]));
726 }
727
728 //template ExtendFunType(alias fun, T...)
729 //{
730 //    static if (is(typeof(fun(T.init))))
731 //        alias typeof(fun(T.init)) ExtendFunType;
732 //    else
733 //        alias T[0] ExtendFunType;
734 //}
735
736 struct ExtendFun(alias fun)
737 {
738     auto opCall(T...)(T t)
739     {
740         static if ( isFunction!fun && is(ParameterTypeTuple!fun) && is(ParameterTypeTuple!fun == TypeTuple!T) ) // non-templated function
741             return fun(t);
742 //        else static if (is(typeof(fun) == string) && is(typeof( naryFun!fun(t) ))) // templated function
743 //            return naryFun!fun(t);
744         else
745             return t[0];
746     }
747 }
748
749 /**
750 Takes a function $(M foo) and 'extends' it, allowing it to accept any type of argument.
751 If the arguments types are compatible with $(M foo), returns foo(args) otherwise, it just returns
752 the argument.
753
754 That may seem a strange template to define, but it's quite useful for mapping a tuple (see $(M dranges.tuple.mapTuple)
755 and $(M dranges.tupletree.mapTree)).
756 Suppose you have a tuple and want to change only the strings in it. Define $(M foo) to act on strings, extend it with
757 $(M _extendFun!foo) and voila, you can then map $(M _extendFun!foo) on your tuple: the strings will be transformed, leaving the
758 other types untouched. I learnt the trick from a Haskell article.
759
760 Example:
761 ----
762 import dranges.tuple;
763
764 auto t = tuple("bin", 1024, 3.14159,
765                "src", 0,    1.0,
766                "myDirectory/foo", 100, -2.3);
767
768 string foo(string s) { return "std/" ~ s;}
769
770 auto efoo = extendFun!foo; // beware: it's not alias extendFun!foo efoo;, as for other templates around here.
771
772 auto t2 = mapTuple ! efoo (t);
773
774 assert(t2 == tuple("std/bin", 1024, 3.14159,
775                    "std/src", 0,    1.0,
776                    "std/myDirectory/foo", 100, -2.3));
777 ----
778 */
779 //ExtendFun!fun extendFun(alias fun)()
780 //{
781 //    ExtendFun!(fun) efun;
782 //    return efun;
783 //}
784
785 template extendFun(alias fun)
786 {
787     auto extendFun(T...)(T t)
788     {
789         alias naryFun!fun nfun;
790         static if (is(typeof(nfun(t))))
791             return nfun(t);
792         else
793             return t[0];
794     }
795 }
796
797 version(unittest)
798 {
799     import dranges.tuple;
800     string foo(string s) { return "std/" ~ s;}
801 }
802
803 unittest
804 {
805     auto t = tuple("bin", 1024, 3.14159,
806                    "src", 0,    1.0,
807                    "myDirectory/foo", 100, -2.3);
808
809     auto efoo = extendFun!foo;
810
811     auto t2 = mapTuple ! efoo (t);
812
813     assert(t2 == tuple("std/bin", 1024, 3.14159,
814                        "std/src", 0,    1.0,
815                        "std/myDirectory/foo", 100, -2.3));
816 }
817
818 struct ExtendFun0(alias fun, D)
819 {
820     D defaultValue;
821
822     typeof(fun(Init!T)) opCall(T...)(T t) if (is(typeof(fun(t))))
823     {
824         return fun(t);
825     }
826
827
828     D opCall(T...)(T t) if (!is(typeof(fun(t))))
829     {
830         return defaultValue;
831     }
832 }
833
834 /**
835 Same as before, but with a default value returned when extendFun is offered
836 an arg that $(M foo) cannot accept. The default value can be of any type.
837
838 Example:
839 ----
840 import dranges.tuple;
841
842 auto t = tuple("bin", 1024, 3.14159,
843                "src", 0,    1.0,
844                "myDirectory/foo", 100, -2.3);
845
846 string foo(string s) { return "std/" ~ s;}
847
848 auto efoo = extendFun0!foo(0);
849
850 auto t2 = mapTuple ! efoo (t);
851
852 assert(t2 == tuple("std/bin",               0, 0,
853                    "std/src",               0, 0,
854                    "std/myDirectory/foo",   0, 0));
855 ----
856 */
857 ExtendFun0!(fun, D) extendFun0(alias fun, D)(D defaultValue)
858 {
859     ExtendFun0!(fun,D) efun;
860     efun.defaultValue = defaultValue;
861     return efun;
862 }
863
864 unittest
865 {
866     auto t = tuple("bin", 1024, 3.14159,
867                    "src", 0,    1.0,
868                    "myDirectory/foo", 100, -2.3);
869
870     auto efoo0 = extendFun0!foo(0); // foo is defined in a version(unittest) statement higher up in the code
871
872     auto t2 = mapTuple ! efoo0 (t);
873
874     assert(t2 == tuple("std/bin",               0, 0,
875                        "std/src",               0, 0,
876                        "std/myDirectory/foo",   0, 0));
877 }
878
879 /**
880 This is just a wrapper around the $(M match) function found in $(M dranges.patternmatch), here to emphasize
881 the way $(M match) is just a many-types-to-many-types 'function'. Explained a bit more clearly, $(M _eitherFun)
882 takes any number of functions and keep them near its hot little heart. When passed an argument, it will
883 successively test each function and returns the result of the first one that matches. No match means it will
884 throw a NoMatch exception. Functions are tested the same order they were passed as arguments.
885
886 How is this different from overloading, will you ask? I'm glad you did:
887
888 $(UL
889   $(LI first, you can use it to 'group' many different functions, from different origins and different names.)
890   $(LI second (and that may be the most important point), it's a template, so the return
891 type of $(M _eitherFun) can be different for each argument type. So you can use it to map a range, but also a tuple, with $(M dranges.tuple.mapTuple).)
892   $(LI third, it accepts template functions. In fact, it even accepts 'string' functions, as in "a+b*c-d.expand". See the $(M patternmatch)
893 module documentation for more explanations.)
894   $(LI fourth, once it's defined, you can pass it around as one entity. Most notably, it can becomes the argument
895     of another meta-function there or even the argument to another $(M _eitherFun!))
896 )
897
898 So, in functional languages terms, it's a sum of functions (just as $(M juxtapose) is a product).
899
900 Example:
901 ----
902 int    f1(int i) { return i;}
903 double f2(double d) { return d*d;}
904 int    f3(int i, string s) { return i;}
905 string f4(string s, int i) { return s;}
906
907 alias eitherFun!(f1,f2,f3,f4) efun; // efun accepts either an int, or a double, or a (int,string) or a (string, int)
908
909 assert(efun(1) == 1);
910 assert(efun(1.5) == 2.25);
911 assert(efun(1,"abc") == 1);
912 assert(efun("abc",1) == "abc");
913
914 // Let's extend it, then.
915 int[] f5(int[] i) { return i.reverse;}
916
917 alias eitherFun!(efun, f5) efun5;   // efun5 will test f1, then f2, ... and f5 at last resort.
918 // alias eitherFun(f5, efun) efun5bis would have tested f5 first, then f1, ...
919
920 assert(efun5(1) == 1);              // efun5 is like efun
921 assert(efun5(1.5) == 2.25);
922 assert(efun5(1,"abc") == 1);
923 assert(efun5("abc",1) == "abc");
924 assert(efun5([0,1,2]) == [2,1,0]);  // except it also accepts an array of ints as argument.
925 ----
926
927 Note: as said before, functions are tested in the same order they were passed as arguments. So a function can 'swallow' arguments
928 that could have been accepted by another, downstream function.
929 */
930 template eitherFun(F...)
931 {
932     alias match!(StaticMap!(naryFun, F)) eitherFun;
933 }
934
935 unittest
936 {
937     int f1(int i) { return i;}
938     double f2(double d) { return d*d;}
939     int f3(int i, string s) { return i;}
940     string f4(string s, int i) { return s;}
941
942     int[] f5(int[] i) { return i.reverse;}
943
944     alias eitherFun!(f1,f2,f3,f4) efun;
945     assert(efun(1) == 1);
946     assert(efun(1.5) == 2.25);
947     assert(efun(1,"abc") == 1);
948     assert(efun("abc",1) == "abc");
949
950     alias eitherFun!(efun, f5) efun5;
951
952     assert(efun5(1) == 1);
953     assert(efun5(1.5) == 2.25);
954     assert(efun5(1,"abc") == 1);
955     assert(efun5("abc",1) == "abc");
956     assert(efun5([0,1,2]) == [2,1,0]);
957 }
958
959 /**
960 A simple adapter, when you have a complicated function you do not want to touch (or cannot) touch. It
961 applies the $(M pre) preprocessing to the arguments, calls fun and then postprocess the result. The
962 default for post is "a", that is the identity string function. So the two args version of $(M _adaptFun)
963 just deals with adapting the arguments.
964 */
965 template adaptFun(alias pre, alias fun, alias post = "a")
966 {
967     typeof(naryFun!post(naryFun!fun(naryFun!pre(Init!T)))) adaptFun(T...)(T t)
968     {
969         return naryFun!post(naryFun!fun(naryFun!pre(t)));
970     }
971 }
972
973
974 /**
975 The composition 'power' of a function: $(M fun(fun(fun(x)...))), n times. n == 1 is the same
976 as $(M fun) and n = 0 is the identity function (just returns the arguments).
977
978 Example:
979 ----
980 int inc(int i) { return i+1;}
981 string conc(string s) { return s ~ s;}
982
983 alias powerFun!(inc, 5) plus5; // calls inc(inc(inc(inc(inc(t))))), so returns t+5
984 alias powerFun!(inc, 1) plus1;
985 alias powerFun!(inc, 0) plus0;
986
987 assert(plus5(4) == 9);
988 assert(plus1(4) == 5);
989 assert(plus0(4) == 4);
990
991 alias powerFun!(conc, 2) conc2;
992
993 assert(conc("abc") == "abcabc");
994 assert(conc2("abc") == "abcabcabcabc");
995 assert(conc2("abc") == conc(conc("abc")));
996 ----
997 */
998 template powerFun(alias fun, size_t n)
999 {
1000     auto powerFun(T...)(T args)
1001     {
1002         return wrapCode!(fun, n)(args);
1003     }
1004 }
1005
1006 unittest
1007 {
1008     int inc(int i) { return i+1;}
1009     string conc(string s) { return s ~ s;}
1010
1011     alias powerFun!(inc, 5) plus5;
1012     alias powerFun!(inc, 1) plus1;
1013     alias powerFun!(inc, 0) plus0;
1014
1015     assert(plus5(4) == 9);
1016     assert(plus1(4) == 5);
1017     assert(plus0(4) == 4);
1018
1019     alias powerFun!(conc, 2) conc2;
1020
1021     assert(conc("abc") == "abcabc");
1022     assert(conc2("abc") == "abcabcabcabc");
1023     assert(conc2("abc") == conc(conc("abc")));
1024 }
1025
1026 /**
1027 Takes a function and store default values for its last arguments. For a n-arg function,
1028 you can provided d default values, d being between 0 and n. These values will be applied
1029 to the last d arguments.
1030
1031 Example:
1032 ----
1033 int foo(int i, int j, double k) { return i+j+to!int(k);}
1034 auto dfoo = withDefaultValues!(foo)(2,1.5); // two default values provided -> 2 for j and 1.5 for k
1035                                             // so dfoo can accept 1, 2 or 3 arguments.
1036
1037 assert(dfoo(1)         == foo(1, 2, 1.5)); // 1 arg given -> dfoo use two defaults
1038 assert(dfoo(1, 1)      == foo(1, 1, 1.5)); // 2 args -> one default
1039 assert(dfoo(1, 1, 0.5) == foo(1, 1, 0.5)); // 3 args -> no default
1040 ----
1041
1042 Most of the time, $(M _withDefaultValues) will determine the arity of your function. In case of doubt, you can provide it as
1043 a second template argument, like this:
1044 ----
1045 A bar(A,B)(A a0, A a1, B a2, Tuple!(A,B) a3) { return a0;} // template function, withDefaultValues cannot determine the arity is 4
1046 auto dbar = withDefaultValues!(bar, 4)(2, tuple(2, 3.14));
1047 ----
1048
1049 TODO: No, that should be possible now that I have a template to determine the arity even of template functions.
1050 */
1051 DefaultValues!(fun, arity!fun, D) withDefaultValues(alias fun, D...)(D defaults) if (D.length <= arity!fun)
1052 {
1053     DefaultValues!(fun, arity!fun, D) def;
1054     def._defaults = defaults; // to avoid some conflict between this() and opCall() in the struct
1055     return def;
1056 }
1057
1058 /// ditto
1059 DefaultValues!(fun, arity, D) withDefaultValues(alias fun, size_t arity, D...)(D defaults) if (D.length <= arity)
1060 {
1061     DefaultValues!(fun, arity, D) def;
1062     def._defaults = defaults; // to avoid some conflict between this() and opCall() in the struct
1063     return def;
1064 }
1065
1066 struct DefaultValues(alias fun, size_t arity, D...)
1067 {
1068     D _defaults;
1069     auto opCall(T...)(T t)
1070     {
1071         static if ( arity - D.length <= T.length && T.length <= arity )
1072             return naryFun!fun(t,_defaults[D.length+T.length-arity..$]);
1073         else
1074             static assert(false, "withDefaultValues: bad number of arguments. Need between "
1075                                 ~ to!string(arity - D.length) ~ " and " ~ to!string(arity) ~ " arguments, got " ~ to!string(T.length)~".");
1076     }
1077 }
1078
1079 version(unittest)
1080 {
1081     int foo3(int i, int j, double k) { return i+j+to!int(k);}
1082 }
1083
1084 unittest
1085 {
1086     auto dfoo = withDefaultValues!(foo3)(2,1.5); // two default values provided -> for j and for k
1087                                                 // so dfoo can accept 1, 2 or 3 arguments.
1088
1089     assert(dfoo(1)         == foo3(1, 2, 1.5)); // 1 arg given -> dfoo use two defaults
1090     assert(dfoo(1, 1)      == foo3(1, 1, 1.5)); // 2 args -> one default
1091     assert(dfoo(1, 1, 0.5) == foo3(1, 1, 0.5)); // 3 args -> no default
1092 }
1093
1094 /**
1095 Accepts a $(M class) or $(M struct) name as template argument and creates a factory function that creates
1096 the corresponding $(M class)/$(M struct). It allows one to map a constructor on a range, to create a
1097 range of classes. It's not possible normally.
1098
1099 Example:
1100 ----
1101 class C {
1102     int i;
1103     this(int _i) { i = _i;}
1104 }
1105
1106 auto arr = [0,1,2,3];
1107
1108 // auto m = map!C(arr); // does not work.
1109 alias construct!C CC;
1110 auto m = map!CC(arr); // works;
1111 // m is like [new C(0), new C(1), new C(2), new C(3)]
1112 ----
1113
1114 What's fun is when you use it on many-args constructors or structs:
1115 ----
1116 struct S { int i; double d;}
1117
1118 alias construct!S CS;
1119
1120 auto s = tmap!CS([0,1,2,3], [-1.1,-2.2,3.3,4.]); // Yeah, tmap
1121 assert(equal(s, [S(0,-1.1), S(1, -2.2), S(2, 3.3), S(3, 4.0)]));
1122 ----
1123 */
1124 template construct(Struct) if (is(Struct == struct))
1125 {
1126     Struct construct(T...)(T t)
1127     {
1128         return Struct(t);
1129     }
1130 }
1131
1132 /// ditto
1133 template construct(Class) if (is(Class == class))
1134 {
1135     Class construct(T...)(T t)
1136     {
1137         return new Class(t);
1138     }
1139 }
1140
1141 version(unittest)
1142 {
1143     class C {
1144         int i;
1145         this(int _i) { i = _i;}
1146     }
1147 }
1148
1149 unittest
1150 {
1151
1152     auto arr = [0,1,2,3];
1153
1154     // auto m = map!C(arr); // does not work.
1155     alias construct!C CC;
1156     auto m = map!CC(arr); // works;
1157
1158     struct S { int i; double d;}
1159
1160     alias construct!S CS;
1161
1162     auto s = tmap!CS([0,1,2,3], [-1.1,-2.2,3.3,4.]); // Yeah, tmap
1163     assert(equal(s, [S(0,-1.1), S(1, -2.2), S(2, 3.3), S(3, 4.0)]));
1164 }
1165
1166 /**
1167 Transforms a function accepting $(M (T, T, T, ...)) into a function accepting $(M (T[])). The new function
1168 will consume as many arguments as needed, but won't throw if there are more.
1169
1170 Example:
1171 ----
1172 int foo(int i, int j, int k) { return i+j+k;}
1173
1174 alias arrayify!foo afoo;
1175 assert(afoo([1,2,3]) == 1+2+3);
1176 ----
1177 */
1178 template arrayify(alias fun) if (isFunction!fun && is(CommonType!(ParameterTypeTuple!fun)))
1179 {
1180     ReturnType!fun arrayify(CommonType!(ParameterTypeTuple!fun)[] args)
1181     {
1182         alias TypeNuple!(CommonType!(ParameterTypeTuple!fun), ParameterTypeTuple!fun.length) TN;
1183         TN tn;
1184         foreach(i, Type; TN) tn[i] = args[i];
1185         return fun(tn);
1186     }
1187 }
1188
1189 /**
1190 Transforms a function accepting a $(M (T,T,T,...)) into a function accepting a range of $(M T)s.
1191 */
1192 template rangify(alias fun) if (isFunction!fun && is(CommonType!(ParameterTypeTuple!fun)))
1193 {
1194     ReturnType!fun rangify(R)(R range) if (isForwardRange!R && is(ElementType!R == CommonType!(ParameterTypeTuple!fun)))
1195     {
1196         alias TypeNuple!(CommonType!(ParameterTypeTuple!fun), ParameterTypeTuple!fun.length) TN;
1197         TN tn;
1198         foreach(i, Type; TN) { tn[i] = range.front; range.popFront;}
1199         return fun(tn);
1200     }
1201 }
1202
1203 /**
1204 Transforms a function into a tuple-accepting function. Useful to map a standard function
1205 on a tuple-producing range. A parameterless function (zero args) is left untouched.
1206
1207 See_Also: $(M tmap), $(M tfilter), $(M comp) and $(M pComp) in $(M dranges.algorithm).
1208
1209 Example:
1210 ----
1211 string foo3(int a, string b, double c) {
1212     return to!string(a) ~ "+" ~ b ~ "+" ~ to!string(c);
1213 }
1214
1215 auto tfoo3 = tuplify!foo3;
1216 auto t = tuple(1, "a", 3.0);
1217 auto result = tfoo3(t);
1218 assert(result == "1+a+3");
1219
1220 string foo() {
1221     return "aha";
1222 }
1223 auto tfoo = tuplify!foo;
1224 assert(tfoo() == "aha");
1225 ----
1226 */
1227 template tuplify(alias fun) {
1228     static if(isFunction!fun)
1229         alias tuplifyImpl!(fun).result tuplify;
1230 //    else static if (is(fun = struct)) // struct name -> constructor
1231 //        alias construct!fun
1232 }
1233
1234 template tuplifyImpl(alias fun) if (isFunction!fun) {
1235     alias ReturnType!fun R;
1236     alias ParameterTypeTuple!fun A;
1237     static if (A.length > 0) {
1238         R result(Tuple!(A) tup) {
1239                 return fun(tup.field);
1240         }
1241     }
1242     else {
1243         R result() {
1244             return fun();
1245         }
1246     }
1247 }
1248
1249
1250 //
1251 //auto tuplify(R, A...)(R delegate(A) fun) {
1252 //    static if (A.length == 0) {
1253 //        return fun;
1254 //    }
1255 //    else {
1256 //        R tuplified(Tuple!(A) tup) {
1257 //            return tupleApply!fun(tup);
1258 //        }
1259 //        return &tuplified;
1260 //    }
1261 //}
1262 //
1263 unittest {
1264     string foo3(int a, string b, double c) {
1265         return to!string(a) ~ "+" ~ b ~ "+" ~ to!string(c);
1266     }
1267
1268     alias tuplify!foo3 tfoo3;
1269     auto t = tuple(1, "a", 3.0);
1270     auto result = tfoo3(t);
1271     assert(result == "1+a+3");
1272
1273     string foo() { return "aha";}
1274     alias tuplify!foo tfoo;
1275     assert(tfoo == "aha");
1276 }
1277
1278 /**
1279 A simple adaptor for $(M fun), making it accept supplementary arguments of type $(M T...).
1280 See_Also: $(M makeVariadic).
1281 */
1282 template addArgs(alias fun, T...)
1283 {
1284     ReturnType!fun addArgs(ParameterTypeTuple!fun args, T newArgs)
1285     {
1286         return fun(args);
1287     }
1288 }
1289
1290
1291 /**
1292 Takes a standard function, and makes it variadic: it will accept any number of surnumerary arguments of any type
1293 after the 'normal' ones that it had before. It's useful to 'adapt' a function to a range (with
1294 automatic unpacking of tuples, like for $(M tmap)).
1295
1296 Example:
1297 ----
1298 int foo(int i) { return i;}
1299 alias makeVariadic!foo vfoo;
1300 auto i = vfoo(1, 2,3,'a', "hello there!");
1301 assert(i == 1);
1302 ----
1303 */
1304 template makeVariadic(alias fun)
1305 {
1306     ReturnType!fun makeVariadic(ParameterTypeTuple!fun args, ...) { return fun(args);}
1307 }
1308
1309 template RT(alias fun)
1310 {
1311     template RT(T)
1312     {
1313         alias typeof(fun(T.init)) RT;
1314     }
1315 }
1316
1317 template RT2(alias fun)
1318 {
1319     template RT2(T,U)
1320     {
1321         alias typeof(fun(T.init, U.init)) RT2;
1322     }
1323 }
1324
1325 template RTS(alias fun)
1326 {
1327     template RTS(Ts...)
1328     {
1329         alias typeof(fun(Ts.init)) RTS;
1330     }
1331 }
1332
1333 template IsBetween(char c, char a, char b) {
1334     static if ((to!int(c) >= to!int(a)) && (to!int(c) <= to!int(b) )) {
1335         enum bool IsBetween = true;
1336     }
1337     else {
1338         enum bool IsBetween = false;
1339     }
1340 }
1341
1342 template IsOneChar(char a, char b, char c)
1343 {
1344     static if(!(IsBetween!(a, 'A', 'Z') || IsBetween!(a, 'a', 'z'))
1345            &&   IsBetween!(b, 'a', 'z')
1346            && !(IsBetween!(c, 'A', 'Z') || IsBetween!(c, 'a', 'z')))
1347     {
1348         enum bool IsOneChar = true;
1349     }
1350     else
1351     {
1352         enum bool IsOneChar = false;
1353     }
1354 }
1355
1356 template CharArity(char a)
1357 {
1358     enum int CharArity = to!int(a) - 96;
1359 }
1360
1361 template aritySImpl(string s, size_t index)
1362 {
1363     static if (s.length > 3)
1364     {
1365         static if (IsOneChar!(s[0], s[1], s[2]) && (CharArity!(s[1])>index))
1366             alias aritySImpl!(s[1..$], CharArity!(s[1])).result result;
1367         else
1368             alias aritySImpl!(s[1..$], index).result result;
1369     }
1370     else
1371     {
1372         static if (s.length == 3) {
1373             static if (IsOneChar!(s[0], s[1], s[2]) && (CharArity!(s[1])>index))
1374                 alias CharArity!(s[1]) result;
1375             else
1376                 alias index result;
1377         }
1378         else
1379             enum size_t result = 0;
1380     }
1381 }
1382
1383 /**
1384 Is true iff $(M fun) can be applied on the TypeTuple $(M ARGS).
1385 Example:
1386 ----
1387 assert(CompatibilityFuncArgs!("a+b", int, int)); // 'string' function are templated by unaryFun or binaryFun
1388                                                  // They will always be compatible with their args
1389 assert(CompatibilityFuncArgs!(binaryFun!"a+b", int, int));
1390
1391 int foo(int a, double b) { return a;}
1392 assert(CompatibilityFuncArgs!(foo, int, double));
1393 assert(CompatibilityFuncArgs!(foo, int, int)); // You can pass an int as second argument for foo, as it will be converted
1394 assert(!CompatibilityFuncArgs!(foo, double, double));  // But not a double as first arg.
1395 assert(!CompatibilityFuncArgs!(foo, int, string));
1396
1397 int bar() { return 0;}
1398 assert(CompatibilityFuncArgs!bar); // For bar, no args...
1399 assert(CompatibilityFuncArgs!(bar, TypeTuple!())); // For bar, no args...
1400
1401 assert(CompatibilityFuncArgs!((int a) { return -a;}, int)); // Works for anonymous functions
1402 ----
1403 */
1404 template CompatibilityFuncArgs(alias fun, ARGS...) if (isFunction!(fun)) {
1405     enum bool CompatibilityFuncArgs = __traits(compiles, {
1406                                                             ARGS args;
1407                                                             fun(args);
1408                                                          }
1409                                               );
1410 }
1411
1412 template CompatibilityFuncArgs(alias fun, ARGS...) if (!isFunction!(fun)) {
1413    static if (is(typeof(fun) : string)) {
1414         enum bool CompatibilityFuncArgs = true;
1415     }
1416     else {
1417         enum bool CompatibilityFuncArgs = __traits(compiles, {
1418                                                                 ARGS args;
1419                                                                 fun!(ARGS)(args);
1420                                                             }
1421                                                    );
1422     }
1423 }
1424
1425 unittest {
1426     assert(CompatibilityFuncArgs!("a+b", int, int)); // 'string' function are templated by unaryFun or binaryFun
1427                                                      // They will always be compatible with their args
1428     assert(CompatibilityFuncArgs!(binaryFun!"a+b", int, int));
1429
1430     int foo(int a, double b) { return a;}
1431     assert(CompatibilityFuncArgs!(foo, int, double));
1432     assert(CompatibilityFuncArgs!(foo, int, int)); // You can pass an int as second argument for foo, as it will be converted
1433     assert(!CompatibilityFuncArgs!(foo, double, double));  // But not a double as first arg.
1434     assert(!CompatibilityFuncArgs!(foo, int, string));
1435
1436     int bar() { return 0;}
1437     assert(CompatibilityFuncArgs!bar); // For bar, no args...
1438     assert(CompatibilityFuncArgs!(bar, TypeTuple!())); // For bar, no args...
1439
1440     assert(CompatibilityFuncArgs!((int a) { return -a;}, int)); // Works for anonymous functions
1441 }
1442
1443
1444 template Loop(uint n, uint max, alias Action)
1445 {
1446     static if (n < max) {
1447         enum string Loop = Action(n, max) ~ Loop!(n+1, max, Action);
1448     }
1449     else{
1450         enum string Loop = "";
1451     }
1452 }
1453
1454 string PTL(uint n, uint max) { return "ElementType" ~ to!string(n) ~ (n < max-1 ? ", " : "");}
1455 string PNL(uint n, uint max) { return " ElementType" ~ to!string(n) ~ " " ~ az(n) ~ ";";}
1456 string BNL(uint n, uint max) { return " ElementType" ~ to!string(n) ~ " __" ~ az(n) ~ (n < max-1 ? ", " : "");}
1457 string AL(uint n, uint max)  { return " alias __" ~ az(n) ~ " " ~ az(n) ~ ";";}
1458
1459 /**
1460 A generalization of $(M std.functional.unaryFun) and $(M .binaryFun) for as many params as you need, in the 'a' - 'z' (included)
1461 range. You can indicate the desired final arity if you want, but otherwise a compile-time heuristics
1462 tries to determine the string's 'arity'.
1463 As for $(M unaryFun) and $(M binaryFun), 'a' means first argument, 'b' the second and so on.
1464 As for $(M unaryFun) and $(M binaryFun), it creates a templated function, with the type of each parameter left undecided.
1465 As for $(M unaryFun) and $(M binaryFun), it does not change $(M fun) if it's already a function.
1466
1467 Examples:
1468 ----
1469 alias naryFun!("a+b*c-d") test4;  // Creates a templated 4-args function test4(A, B, C, D)(A a, B b, C c, D d) { return a+b*c-d;}
1470 assert(test4(1,2,3,4) == 3);        // instantiate test4!(int, int, int, int)
1471 assert(test4(1.0,2.0,3,4) == 3.0);  // instantiate test4!(double, double, int, int)
1472
1473 alias naryFun!("a+b",3) test3;      // You can create a fun with more args than necessary, if you wish
1474 assert(test3(1,2,100) == 3);        // without the 3, naryFun!"a+b" would create a binary function.
1475 assert(test3(1.0,2.0,100) == 3.0);
1476
1477 alias naryFun!"sin(a)+cos(b)*c" testsincos; // functional.d imports a lot of other D modules, to have their functions accessible.
1478
1479 alias naryFun!"tuple(a,a,a)" toTuple;
1480 assert(toTuple(1) == tuple(1,1,1));
1481
1482 alias naryFun!"a.expand[1]" tuple1; // tuple1 will be created, but can be used only on types defining a .expand field.
1483 assert(tuple1(toTuple(1)) == 1);
1484
1485 alias naryFun!"[b,a,c]" arrayTwister; // will return a static array
1486 assert(arrayTwister(0,1,2) == [1,0,2]);
1487
1488 alias naryFun!"f" projection6; // 'a' -> 1 arg, 'b' -> binary, ..., 'f' -> 6-args function. In this case, returning only its sixth argument.
1489 assert(projection6(0,1,2,3,4,5) == 5);
1490
1491 alias naryFun!"3" test0;               // A 0-arg function. It's exactly: int test0() { return 3;}
1492 assert(test0 == 3);                    // Constant return
1493 assert(is(typeof(test0) == function)); // But it's a function, not a constant.
1494
1495 int foo(int a, int b) { return a*b;}
1496 alias naryFun!(foo) nfoo;           // function test
1497 assert(nfoo(2,3) == 6);
1498
1499 int bar() { return 1;}
1500 alias naryFun!bar nbar;             // 0-arg function test
1501 assert(nbar == 1);
1502 ----
1503 */
1504 template naryFun(string fun, uint Nparam)
1505 {
1506     alias naryFunImpl!(fun, Nparam).result naryFun;
1507 }
1508 /// ditto
1509 template naryFun(string fun)
1510 {
1511     alias naryFunImpl!(fun, arity!fun).result naryFun;
1512 }
1513
1514 // Works OK, but only at runtime. I need to code this for compile-time.
1515 // OK, done.
1516 // may 2010: CTFE got better with recent DMD version. I should give it a try again.
1517 /*
1518 size_t arityHeuristics(string s) {
1519     auto padded = " " ~ s ~ " ";
1520     char[] paddedchars = cast(char[])padded; // To get rid of those pesky immutable(char)
1521     bool isaz(char c) { return isOneOf!lowercase(c);} // lowercase is defined in std.string
1522     bool isazAZ(char c) { return isOneOf!letters(c);} // letters is defined in std.string
1523     bool isOneChar(char a, char b, char c) { return !isazAZ(a) && isaz(b) && !isazAZ(c);}
1524     size_t charArity(char c) { return to!int(c)-96;} // 1 for 'a', 2 for 'b'
1525     size_t loneIndex(char a, char b, char c) { return isOneChar(a,b,c) ? charArity(b) : 0;}
1526     auto loneIndices = nMap!loneIndex(paddedchars);
1527     return reduce!max(loneIndices);
1528 }
1529 */
1530
1531 template naryFunImpl(alias fun, uint Nparam) if (is(typeof(fun) : string))
1532 {
1533     static if (Nparam > 0)
1534     {
1535         enum string paramTypeList = Loop!(0, Nparam, PTL);
1536         enum string paramNameList = Loop!(0, Nparam, PNL);
1537         enum string bodyNameList  = Loop!(0, Nparam, BNL);
1538         enum string aliasList     = Loop!(0, Nparam, AL);
1539         enum string code = "typeof({" ~ paramNameList ~ " return (" ~ fun ~ ");}()) result(" ~ paramTypeList ~ ")(" ~ bodyNameList ~ ") { " ~ aliasList ~ " return (" ~ fun ~ ");}";
1540     }
1541     else
1542     {
1543         enum string code = "typeof((){return " ~ fun ~ ";}()) result() {return " ~fun ~ ";}";
1544     }
1545
1546     mixin(code);
1547 }
1548
1549 /// ditto
1550 template naryFun(alias fun, uint Nparam) if (!is(typeof(fun): string))// && (arity!(fun) == Nparam))
1551 {
1552     static if (is(fun == struct) || is(fun == class)) // class or struct constructor
1553         alias construct!fun naryFun;
1554     else
1555         alias fun naryFun;
1556 }
1557
1558 /// ditto
1559 template naryFun(alias fun) if (!is(typeof(fun): string))
1560 {
1561     alias fun naryFun;
1562 }
1563
1564 unittest
1565 {
1566     alias naryFun!("a+b*c-d") test4;  // Creates a templated 4-args function test4(A, B, C, D)(A a, B b, C c, D d) { return a+b*c-d;}
1567     assert(test4(1,2,3,4) == 3);        // instantiate test4!(int, int, int, int)
1568     assert(test4(1.0,2.0,3,4) == 3.0);  // instantiate test4!(double, double, int, int)
1569
1570     alias naryFun!("a+b",3) test3;      // You can create a fun with more args than necessary, if you wish
1571     assert(test3(1,2,100) == 3);        // without the 3, naryFun!"a+b" would create a binary function.
1572     assert(test3(1.0,2.0,100) == 3.0);
1573
1574     alias naryFun!"sin(a)+cos(b)*c" testsincos; // functional.d imports a lot of other D modules, to have their functions accessible.
1575
1576     alias naryFun!"tuple(a,a,a)" toTuple;
1577     assert(toTuple(1) == tuple(1,1,1));
1578
1579     alias naryFun!"a.expand[1]" tuple1; // tuple1 will be created, but can be used only on types defining a .expand field.
1580     assert(tuple1(toTuple(1)) == 1);
1581
1582     alias naryFun!"[b,a,c]" arrayTwister; // will return a static array
1583     assert(arrayTwister(0,1,2) == [1,0,2]);
1584
1585     alias naryFun!"f" projection6; // 'a' -> 1 arg, 'b' -> binary, ..., 'f' -> 6-args function. In this case, returning only its sixth argument.
1586     assert(projection6(0,1,2,3,4,5) == 5);
1587
1588     alias naryFun!"3" test0;               // A 0-arg function. It's exactly: int test0() { return 3;}
1589     assert(test0 == 3);                    // Constant return
1590     assert(is(typeof(test0) == function)); // But it's a function, not a constant.
1591
1592     int foo(int a, int b) { return a*b;}
1593     alias naryFun!(foo) nfoo;           // function test
1594     assert(nfoo(2,3) == 6);
1595
1596     int bar() { return 1;}
1597     alias naryFun!bar nbar;             // 0-arg function test
1598     assert(nbar == 1);
1599 }
1600
1601 /+ deprecated
1602 /**
1603 Fills a TypeTuple of T's (T,T,T, ...) from a T[] array of values. It's
1604 the TypeTuple's length which drives the transfer: it
1605 Used to convert the elements of a Segment (ie: T[]) into a TypeTuple to be used
1606 in a function.
1607 */
1608 void fillFromArray(Arr : T[], T, Tup...)(Arr arr, ref Tup tup) {
1609     static if (Tup.length > 0) {
1610         tup[0] = arr[0];
1611         fillFromArray(arr[1..$], tup[1..$]);
1612     }
1613 }
1614
1615 unittest {
1616     double[] d = [0.0, 1.0, 2.0];
1617     TypeTuple!(double, double, double) td;
1618     fillFromArray(d, td);
1619     assert(td[0] == 0.0);
1620     assert(td[1] == 1.0);
1621     assert(td[2] == 2.0);
1622 }
1623 +/
1624
1625 /+
1626 /**
1627 For a function fun with arguments types (T, T, T, ...) calls the function
1628 from a T[] array of arguments.
1629 Example:
1630 ----
1631 int foo(int a, int b, int c) {
1632     return a*b*c;
1633 }
1634
1635 auto arr = [1,2,3];
1636
1637 // not possible:
1638 // foo(arr);
1639 // so we do:
1640 arrayApply!(foo)(arr); // return 1*2*3 -> 6.
1641 ----
1642 */
1643 auto arrayApply(alias fun, T : U[], U)(T args) if (CompatibilityFuncArgs!(fun, TypeNuple!(U, arity!fun))) {
1644     TypeNuple!(U, arity!fun) at;
1645     fillFromArray(args, at);
1646     return fun(at);
1647 }
1648
1649 unittest {
1650     int foo(int a, int b, int c) {
1651         return a*b*c;
1652     }
1653
1654     auto arr = [1,2,3];
1655
1656     // foo(arr); // not possible
1657     // so we do:
1658     arrayApply!foo(arr); // return 1*2*3 -> 6.
1659 }
1660
1661 /**
1662 Transforms a function with parameters of same type: foo(T, T, T, ...) into an
1663 array-accepting function afoo(T[]). Useful to map a function on a Segment range:
1664 to map a binary or n-ary function on a range. See below.
1665 */
1666 template arrayify(alias fun) {
1667     alias arrayifyImpl!(fun).result arrayify;
1668 }
1669
1670 template arrayify(alias fun, T) {
1671     alias TypeNuple!(T, arity!fun) TN;
1672     alias fun!(TN) fun2;
1673     alias arrayifyImpl!(fun2).result arrayify;
1674 }
1675
1676 template arrayifyImpl(alias fun) {
1677     alias ReturnType!fun R;
1678     alias ParameterTypeTuple!fun A;
1679     static if (A.length > 0) {
1680         R result(A[0][] arr) {
1681             return arrayApply!fun(arr);
1682         }
1683     }
1684     else {
1685         R result() {
1686             return fun();
1687         }
1688     }
1689 }
1690
1691 unittest {
1692     int foo(int a, int b, int c) {
1693         return a*b*c;
1694     }
1695
1696     auto arr = [1,2,3];
1697     alias arrayify!foo afoo; // afoo is now an int[3] or int[] accepting function
1698     assert(is(typeof(&afoo) == int delegate(int[])));
1699     assert(arity!afoo == 1); // afoo is indeed a unary function now.
1700     assert(afoo(arr) == 6); // We can apply afoo on arr.
1701     assert(afoo([2,3,4]) == 24); // Works on int[3] arrays also
1702     assert(!is(afoo([1,2]))); // But afoo rejects int[2] arrays.
1703
1704     auto r1 = [1,2,3,4,5,6];
1705
1706     double average(int a, int b, int c) {
1707         return (a+b+c)/3.0;
1708     }
1709     alias arrayify!average mean;
1710     assert(is(typeof(&mean) == double delegate(int[])));
1711 //    auto s = segment!3(r1); // We cannot map 'average' on s
1712 //    auto m = map!mean(s); // But we can map 'mean'
1713 //    assert(asString(m, " ") == "2 3 4 5");
1714 }
1715 +/
1716
1717 /+ deprecated
1718 /**
1719 Fills a TypeTuple of different types from a std.typecons.Tuple of values.
1720 Used to convert the result of a TupleRange into a TypeTuple to be used
1721 in a function.
1722 */
1723 void fillFromTuple(size_t n = 0, T : Tuple!(TT), TT...)(T tup, ref TT typetup) {
1724     static if (n < TT.length) {
1725         typetup[n] = tup.field[n];
1726         fillFromTuple!(n+1)(tup, typetup);
1727     }
1728 }
1729
1730 unittest {
1731     auto tup = tuple(0, 'a', 1.23);
1732     TypeTuple!(int, char, double) tt;
1733     fillFromTuple(tup, tt);
1734     assert(tt[0] == 0);
1735     assert(tt[1] == 'a');
1736     assert(tt[2] == 1.23);
1737 }
1738
1739 /**
1740 Given a std.typecons.Tuple of values args, expand the Tuple and _apply fun to it.
1741 It's useful to map a n-ary function on a Tuple-outputting range.
1742 Note that apply will check that the Tuple can indeed be used
1743 as parameters for the function. If args is longer than
1744 ParameterTypeTuple!fun, any remaining values will be ignored.
1745
1746 Example:
1747 ----
1748 string foo3(int a, string b, double c) {
1749     return to!string(a) ~ "+" ~ b ~ "+" ~ to!string(c);
1750 }
1751 auto t = tuple(1, "a", 3.0);
1752 writeln(tupleApply!foo3(t)); // Write "1+a+3"
1753 ----
1754 */
1755 auto tupleApply(alias fun, T : Tuple!(R), R...)(T args) if (CompatibilityFuncArgs!(fun, R)) {
1756     TypeTuple!R tt;
1757     fillFromTuple(args, tt);
1758     return fun!(R)(tt[0 .. R.length]);
1759 }
1760
1761 unittest {
1762     string foo3(int a, string b, double c) {
1763         return to!string(a) ~ "+" ~ b ~ "+" ~ to!string(c);
1764     }
1765     auto t = tuple(1, "a", 3.0);
1766     assert(tupleApply!foo3(t) == "1+a+3"); // Applies foo3 to t
1767 }
1768 +/
1769
1770
1771 /**
1772 Internal template to transform a function or a 'string' function
1773 to be applied on a tuple. The $(M T...) part must contains the information
1774 about the args types. It's used to instantiate the correct function
1775 from the template function created by $(M naryFun).
1776
1777 It's used internally by all the tuple-mapping functions: $(M tmap), $(M tfilter), etc.
1778 */
1779 template Prepare(alias fun, T...)
1780 {
1781     alias PrepareImpl!(fun, T).result Prepare;
1782 }
1783
1784 template PrepareImpl(alias fun, T...)
1785 {
1786     alias naryFun!(fun, T.length) nfun; // transforms string as n-args templated function.
1787     static if (__traits(compiles, nfun!T)) // Can I instantiate nfun!T?
1788         alias nfun!T infun;  // instantiates n-fun.
1789     else
1790         alias nfun infun;    // It's a function, do nothing.
1791     alias tuplify!infun result;
1792 }
Note: See TracBrowser for help on using the browser.