On Sat, Sep 4, 2010 at 01:40, Simen kjaeraas <simen.kja...@gmail.com> wrote:
> Simen kjaeraas <simen.kja...@gmail.com> wrote: > > I believe this will only work with arrays as input. Either that, or I need >> a way to make this work: >> >> struct Foo( R ) if ( isForwardRange!R ) { >> bool delegate( ElementType!R ) bar; >> Filter!( bar, R ) range; >> } >> >> Or, well, something like it. I need a static type for a Filter that >> delegates to a struct member, in this case bar. >> > Maybe with a dynamic filter? struct DynamicFilter(R) if (isInputRange!R) { R range; bool delegate(ElementType!R) predicate; bool set; this(R _range) { range = _range; } this(R _range, bool delegate(ElementType!R) _predicate) { range = _range; predicate = _predicate; set = true; popFront(); } void setPredicate(bool delegate(ElementType!R) _predicate) { predicate = _predicate; set = true; popFront();} ElementType!R front() { if (set) { return range.front();} else { throw new Exception("Calling DynamicFilter with an unset predicate.");};} bool empty() { if (set) {return range.empty;} else { throw new Exception("Calling DynamicFilter with an unset predicate.");};} void popFront() { if (set) { while( !range.empty && !predicate(range.front)) { range.popFront(); } } else { throw new Exception("Calling DynamicFilter with an unset predicate."); } } } //DynamicFilter!(R) dynamicFilter(R)(R range) //{ // return DynamicFilter!R(range); //} DynamicFilter!(R) dynamicFilter(R,E)(R range, bool delegate(E) pred = null) if ((isInputRange!R) && is(ElementType!R == E)) { if (pred is null) return DynamicFilter!(R)(range); else return DynamicFilter!R(range, pred); } void main() { auto f = dynamicFilter([0,1,2,3], (int i) { return i%2 == 0;}); writeln(f.front); // 0 f.setPredicate((int i) { return i%2 == 1;}); writeln(f.front); // 1 } Note that in this version, the filtered range always advances. When you change filter, it continues to consume elements from the current point. For backtracking, maybe you need a forward range input, a saved version of this input, and have setPredicate rewind the inner range to the saved version. Philippe