Bug 12655 – foldRange

Status
RESOLVED
Resolution
FIXED
Severity
enhancement
Priority
P1
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2014-04-26T15:53:00Z
Last change time
2016-11-01T12:00:18Z
Assigned to
nobody
Creator
bearophile_hugs

Comments

Comment #0 by bearophile_hugs — 2014-04-26T15:53:13Z
In the C++ STL there is an useful algorithm, that is not well named: http://en.cppreference.com/w/cpp/algorithm/partial_sum An usage example (it does more than just sums): int main() { std::vector<int> v = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; std::cout << "The first 10 even numbers are: "; std::partial_sum(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << '\n'; std::partial_sum(v.begin(), v.end(), v.begin(), std::multiplies<int>()); std::cout << "The first 10 powers of 2 are: "; for (auto n : v) { std::cout << n << " "; } std::cout << '\n'; } The first 10 even numbers are: 2 4 6 8 10 12 14 16 18 20 The first 10 powers of 2 are: 2 4 8 16 32 64 128 256 512 1024 I suggest to add to std.algorithm a related algorithm (with a better name), a lazy range like a reduce/fold that yields all the intermediate results. It is the function present in Mathematica here, named FoldList, but the D version is a lazy range, so a name for the D version is "foldRange" (or "reduceReange"): http://reference.wolfram.com/mathematica/ref/FoldList.html [a, b, ...].foldRange!f(seed) ==> [seed, f(seed, a), f(f(seed, a), b), ...] So given a range of length N it yields a range of length N + 1. A version without seed could also be available. Cumulative sums of the elements of an array: [10, 20, 30, 40].foldRange!q{a + b}(0) ==> [0, 10, 30, 60, 100] [2, 2, 2, 2, 2, 2, 2, 2, 2, 2].foldRange!q{a + b}(0) ==> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
Comment #1 by bearophile_hugs — 2014-07-03T09:03:45Z
Optionally the a+b could be the default operation, like in C++: [10, 20, 30, 40].foldRange(0) ==> [0, 10, 30, 60, 100]
Comment #2 by jens.k.mueller — 2014-07-03T09:11:12Z
*** Issue 13029 has been marked as a duplicate of this issue. ***
Comment #3 by jens.k.mueller — 2014-07-04T11:07:51Z
A cumulate returning the same number elements can be written using map. auto cumulate(alias f, R, T)(R r, T seed) if (isInputRange!R && is(T == ElementType!R)) { import std.algorithm : map; return r.map!(a => a = seed = f(seed, a)); } I leave this here for reference and others to decide whether such a function should be added to Phobos.
Comment #4 by bearophile_hugs — 2015-04-11T18:09:34Z
(In reply to jens.k.mueller from comment #3) > A cumulate returning the same number elements can be written using map. > ... > I leave this here for reference and others to decide whether such a function > should be added to Phobos. It's often a bad idea to define *basic* ranges in terms of others. Because they lose performance. You get short sexy elegant code that dooms all the user code to be slow (sometimes even if you compile with optimizations on).
Comment #5 by john.michael.hall — 2016-09-13T01:48:10Z
I just added a github repository that includes this functionality. I named it scan instead of foldRange because I found scan in more languages. Any feedback is welcome. https://github.com/jmh530/scan
Comment #6 by john.michael.hall — 2016-10-31T20:01:00Z
This can probably be closed now that D 2.072.0 adds cumulativeFold.