1 /** 2 * Copyright: © 2014 Anton Gushcha 3 * License: Subject to the terms of the MIT license, as written in the included LICENSE file. 4 * Authors: NCrashed <ncrashed@gmail.com> 5 */ 6 module dcheck.generator; 7 8 import std.range; 9 import dcheck.maybe; 10 11 /** 12 * Transforms delegate into lazy range. Generation is stopped, when 13 * $(B genfunc) returns $(B Maybe!T.nothing). 14 */ 15 auto generator(T)(Maybe!T delegate() genfunc) 16 { 17 struct Sequencer 18 { 19 private Maybe!T currvalue; 20 21 T front() 22 { 23 assert(!currvalue.isNothing, "Generator range is empty!"); 24 return currvalue.get; 25 } 26 27 bool empty() 28 { 29 return currvalue.isNothing; 30 } 31 32 void popFront() 33 { 34 currvalue = genfunc(); 35 } 36 } 37 static assert(isInputRange!Sequencer); 38 39 auto s = Sequencer(); 40 s.popFront; 41 return s; 42 } 43 /// Example 44 unittest 45 { 46 assert( (() => Maybe!int(1)).generator.take(10).equal(1.repeat.take(10)) ); 47 assert( (() => Maybe!int.nothing).generator.empty); 48 assert( (() 49 { 50 static size_t i = 0; 51 return i++ < 10 ? Maybe!int(1) : Maybe!int.nothing; 52 } 53 ).generator.equal(1.repeat.take(10))); 54 55 class A {} 56 auto a = new A(); 57 58 assert( (() => Maybe!A(a)).generator.take(10).equal(a.repeat.take(10)) ); 59 assert( (() => Maybe!A.nothing).generator.empty); 60 assert( (() 61 { 62 static size_t i = 0; 63 return i++ < 10 ? Maybe!A(a) : Maybe!A.nothing; 64 } 65 ).generator.equal(a.repeat.take(10))); 66 }