/* MAP ITERATOR */ class MapIterator { iter: 'It [Iterable<'It, 'Elem>]; f: 'Elem => 'Trf; } fn iterator(it: MapIterator<'It, 'Elem, 'Trf>) -> MapIterator<'It, 'Elem, 'Trf> { return *it; } fn next(it: @MapIterator<'It, 'Elem, 'Trf>) -> 'Trf { let fnc = it.f; return fnc(it.iter.next()); } fn is_consumed(it: @MapIterator<'It, 'Elem, 'Trf>) -> Bool { return it.iter.is_consumed(); } fn map(it: 'Cont [Iterable<'It, 'Elem>], f: 'Elem => 'Trf) -> MapIterator<'It, 'Elem, 'Trf> { return MapIterator(iterator(move(it)), move(f)); } implement Iterable, 'Trf> for MapIterator<'It, 'Elem, 'Trf>; /* FILTER ITERATOR */ class FilterIterator { iter: 'It [Iterable<'It, 'Elem>]; f: 'Elem => Bool; curr: 'Elem; consumed: Bool; } fn advance_till_true(it: @FilterIterator<'It, 'Elem>) { let fnc = it.f; let iter_i = it.iter; while !iter_i.is_consumed() { it.curr = iter_i.next(); if fnc(*it.curr) { return; } } it.consumed = true; } fn iterator(it: FilterIterator<'It, 'Elem>) -> FilterIterator<'It, 'Elem> { return *it; } fn next(it: @FilterIterator<'It, 'Elem>) -> 'Elem { let res = *it.curr; if it.iter.is_consumed() { it.consumed = true; } it.advance_till_true(); return *res; } fn is_consumed(it: @FilterIterator<'It, 'Elem>) -> Bool { return it.iter.is_consumed() && it.consumed; } fn filter(it: 'Cont [Iterable<'It, 'Elem>], f: 'Elem => Bool) -> FilterIterator<'It, 'Elem> { let iter_i = iterator(move(it)); let res = FilterIterator(move(iter_i), *f, iter_i.next(), false); if !f(*res.curr) { res.advance_till_true(); } return *res; } implement Iterable, 'Elem> for FilterIterator<'It, 'Elem>; // Terminal operators fn sum(it: 'It [Iterable<'It, Int>]) -> Int { let res = 0; for i in move(it) { res := res + i; } return move(res); } fn sum(it: 'It [Iterable<'It, Float>]) -> Float { let res = 0; for i in *it { res := res + i; } return *res; } fn reduce(it: 'It [Iterable<'It, 'Elem>], op: ('Elem, 'Elem) => 'Elem, start: 'Elem) -> 'Elem { let res = move(start); for i in *it { res := op(*res, *i); } return *res; } fn count(it: 'It [Iterable<'It, Int>]) -> Int { let res = 0; for i in move(it) { res.inc(); } return move(res); }