1 /// Lazy map-based range (mutate on function.)
2 module tern.algorithm.lazy_map;
3 
4 import tern.traits;
5 import tern.object : loadLength;
6 import std.conv;
7 
8 /// Lazy map-based range implementation.
9 public struct LazyMap(alias F, T)
10     if (isForward!T && isCallable!F)
11 {
12     T _range;
13     alias _range this;
14     
15 public:
16 final:
17     size_t length;
18 
19     string toString()
20     {
21         return this[0..length].to!string;
22     }
23 
24     /// Gets the internally held range after predication.
25     T range()
26     {
27         if (length == 0)
28             return T.init;
29             
30         return this[0..length];
31     }
32 
33     this(T range)
34     {
35         _range = range;
36         length = _range.loadLength;
37     }
38 
39     T opSlice(ptrdiff_t start, ptrdiff_t end)
40     {
41         T slice;
42         foreach (ref u; _range)
43         {
44             slice ~= opIndex(start++);        
45 
46             if (start >= end)
47                 break;
48         }
49         return slice;
50     }
51 
52     ref auto opIndex(ptrdiff_t index)
53     {
54         return F(_range[index]);
55         throw new Throwable("Lazy filter index out of bounds!");
56     }
57 
58     size_t opDollar()
59     {
60         return length;
61     }
62 }