lambda-dev Digest, Vol 15, Issue 20 [reduce method result type]

Alessio Stalla alessiostalla at gmail.com
Tue Mar 8 07:41:57 PST 2011


On Tue, Mar 8, 2011 at 2:43 PM, Rémi Forax <forax at univ-mlv.fr> wrote:
>  Le 08/03/2011 14:31, Jim Mayer a écrit :
>> // I can tolerate this one
>>      long product(List<Integer>  list) {
>>        return list.map(#{x ->  (long) x}).reduce(0L, #{sum, x ->  sum * x});
>>      }
>
> I prefer this one:
>
>   long product(List<Integer>  list) {
>       return list.lazy().map(#{x ->  (long) x}).reduce(0L, #{sum, x ->  sum * x});
>   }
>
> lazy() means, don't do map directly, but wait and do map and reduce in
> one iteration.

Nice! But still, I don't see a compelling reason to force users to
keep map & reduce strictly distinct operations. It might be cleaner on
a theoretical point of view, but what does it buy in practice to have
the result type match the collection's element type? If for whatever
reason you want to make map and reduce appear in source as separate
steps, you can.
Also, by forcing the types to be the same you require an explicit map
step even in the (imho) important use case where the initial value's
type is a supertype of the collection's element type and the operation
returns the supertype. Silly example (assuming a Number class capable
of generic arithmetic):

Number avg(Collection<? extends Number> data) {
  return data.reduce(Number.ZERO, #{ sum, x -> sum.add(x) }).div(data.size());
}

data could hold integers, fractions, complexes... you'd need an
explicit map step just to upcast to Number (which is not even a
conversion like in the (long) example), else the types won't match.

Just my .02
Alessio


More information about the lambda-dev mailing list