Bug 11084 – std.algorithm.scan

Status
RESOLVED
Resolution
FIXED
Severity
enhancement
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-09-21T05:47:16Z
Last change time
2018-02-10T21:11:46Z
Assigned to
No Owner
Creator
bearophile_hugs

Comments

Comment #0 by bearophile_hugs — 2013-09-21T05:47:16Z
I suggest to add to Phobos a function that returns a range, with usage very similar to std.algorithm.reduce, that returns all the intermediate values. An example from Haskell: Prelude> [1 .. 10] [1,2,3,4,5,6,7,8,9,10] Prelude> scanl (+) 0 [1 .. 10] [0,1,3,6,10,15,21,28,36,45,55] Prelude> scanr (+) 0 [1 .. 10] [55,54,52,49,45,40,34,27,19,10,0] That is also related to the FoldList of Mathematica: http://reference.wolfram.com/mathematica/ref/FoldList.html In D it could work like this: iota(1, 11).scan!q{a + b}(0).writeln ==> [0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
Comment #1 by andrej.mitrovich — 2013-09-21T05:52:21Z
Intermediate? Can you be more specific? What exact steps does that scan!() call make?
Comment #2 by bearophile_hugs — 2013-09-21T06:04:43Z
(In reply to comment #1) > Intermediate? Can you be more specific? What exact steps does that scan!() call > make? The Haskell scanl is a very simple function, it acts very much like reduce, but instead of returning just the last result, it returns them all: scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...] Its whole Haskell implementation in the Haskell Prelude: scanl :: (a -> b -> a) -> a -> [b] -> [a] scanl f q ls = q : (case ls of [] -> [] x:xs -> scanl f (f q x) xs)
Comment #3 by bearophile_hugs — 2013-11-11T05:10:07Z
An example that shows the usage and usefulness of scanl1/scanr1 in Haskell: http://philipnilsson.github.io/Badness10k/articles/waterflow/ Prelude> let h = [2,5,1,2,3,4,7,7,6] Prelude> scanl1 max h [2,5,5,5,5,5,7,7,7] Prelude> scanr1 max h [7,7,7,7,7,7,7,7,6] Prelude> zipWith min (scanl1 max h) (scanr1 max h) [2,5,5,5,5,5,7,7,6] Prelude> let level h = zipWith min (scanl1 max h) (scanr1 max h) Prelude> zipWith (-) (level h) h [0,0,4,3,2,1,0,0,0] Prelude> let water h = sum $ zipWith (-) (zipWith min (scanl1 max h) (scanr1 max h)) h Prelude> water h 10 Where 'scanl1' is a variant of 'scanl' that has no starting value argument: > scanl1 f [x1, x2, ...] == [x1, x1 `f` x2, ...] scanl1 :: (a -> a -> a) -> [a] -> [a] scanl1 f (x:xs) = scanl f x xs scanl1 _ [] = [] And 'scanr1' is a variant of 'scanr' that has no starting value argument: scanr1 :: (a -> a -> a) -> [a] -> [a] scanr1 _ [] = [] scanr1 _ [x] = [x] scanr1 f (x:xs) = f x q : qs where qs@(q:_) = scanr1 f xs In Phobos there are no functions sum ( Issue 4725 ), no zipWith ( Issue 8715 ) and no scanl/scanr/scanl1/scanr1 (this issue), so it takes some more code to translate that Haskell solution to D.
Comment #4 by greensunny12 — 2018-02-10T20:28:11Z
There's cumulativeFold since 2.072: --- import std.algorithm, std.range, std.stdio; void main() { 10.iota.cumulativeFold!((a, b) => a + b).writeln; } --- https://run.dlang.io/is/YIh6I8
Comment #5 by greensunny12 — 2018-02-10T20:33:50Z
PR to reference alternatives names: https://github.com/dlang/phobos/pull/6153
Comment #6 by github-bugzilla — 2018-02-10T21:11:46Z
Commits pushed to master at https://github.com/dlang/phobos https://github.com/dlang/phobos/commit/4775a5e3576843b58f99739d1a9141c810656679 Fix Issue 11084 - std.algorithm.scan https://github.com/dlang/phobos/commit/ae2219c562912e18d0f33fe641adadd18bb62e18 Merge pull request #6153 from wilzbach/mention-scan Fix Issue 11084 - Mention scan in cumulativeFold merged-on-behalf-of: Jack Stouffer <[email protected]>