Using reduce() with tuples created by zip()

Philippe Sigaud philippe.sigaud at gmail.com
Fri Nov 1 02:31:29 PDT 2013


On Thu, Oct 31, 2013 at 8:59 PM, Craig Dillabaugh <
cdillaba at cg.scs.carleton.ca> wrote:

>
>>>
> Thanks, I will try both your, and Bearophile's ideas and see if I
> can figure out how they work.



reduce takes a range and eagerly (that is, not lazily) builds a value from
it. In your case, it builds the squared distance between two points.  The
returned value can be anything: a numerical value, but also another range,
a complex object,  an so on. As long as it can be built increasingly,
you're good.

Given a range [a,b,c,..., z] and a binary function f,
reduce!(f)([a,b,c,...]) calculates f(a,b), then f(f(a,b), c), up to f(...
f( f( f(a,b),c), d), ...,z).

The only question is whether you give it a seed value, or if it takes the
first range element as seed  (f(seed, a), f(f(seed,a),b) and son on).
std.algorithm.reduce provides both overloads.

Note the only thing you get is the final result, not the internal f(f(...'s
applications.

If you want a sum:

reduce!( (result,elem) => result + elem )(range)

or

reduce!( (result,elem) => result + elem )(range, 0)

Sum of squares:

reduce!( (result, elem) => result + elem^^2 )(range, 0)

In your case, the basic element is a tuple, coming from zip. Access to the
two elements is done with [0] or [1]. So:

reduce!( (result, elem) => result + (elem[0]-elem[1])^^2 )(zippedRange, 0)


Of course, it would be easy to write a small n-range reduce helper
function, that takes n ranges and reduces them in parallel:

reduce!( (result, a, b) => result + (a-b)^^2 )(rangeA, rangeB, 0)

Note that reduce is a versatile function: you can duplicate filter and map
functionalities with it. The only thing to remember is that, compared to
other iteration algorithm/ranges, it's eager. Don't use it on an infinite
range!


We could also have a slightly different version that lazily produces the
intermediate results as a range. IIRC, it's called 'scan' in Haskell. It's
sometimes interesting to have it: you can interrupt the ongoing calculation
when the result is 'good enough', not waiting for the entire input range to
be consumed.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d-learn/attachments/20131101/e3906cd5/attachment-0001.html>


More information about the Digitalmars-d-learn mailing list