import std.algorithm; import std.range; import std.traits; import std.functional; import std.typetuple; template scan(alias fun) { auto scan(T, Range)(T start, Range r) if (isInputRange!(Unqual!Range)) { alias binaryFun!fun _fun; struct Result { alias Unqual!Range R; alias typeof(_fun(T.init, .ElementType!R.init)) ElementType; R _input; ElementType _front; this(T start, R input) { _front = start; _input = input; } static if (isInfinite!R) { // Propagate infinite-ness. enum bool empty = false; } else { bool _empty = false; @property bool empty() { return _empty; } } void popFront() { static if (!isInfinite!R) { if (_input.empty) { _empty = true; } } if (!empty) { _front = _fun(_front, _input.front); _input.popFront(); } } @property auto ref front() { return _front; } static if (hasLength!R || isSomeString!R) { @property auto length() { return _input.length; } alias length opDollar; } static if (isForwardRange!R) @property auto save() { auto result = this; result._input = result._input.save; return result; } } return Result(start, r); } } unittest { auto arr = scan!((a,b)=>a+b)(0, [1,2,3,4]); assert(equal(arr, [0,1,3,6,10])); import std.stdio; writeln( scan!"a+b"(0, cast(int[])[]) ); } void main( ) { }