Functional vs simple code
jerro
a at a.com
Tue Oct 2 21:08:47 PDT 2012
> While fiddling with this I came across something that seems odd
> in the behaviour of reduce and wondered if it's intended. It
> rather limits the usefulness of reduce with UFCS to "a + b" and
> "a - b".
>
> Reduce works correctly when provided with a seed argument:
>
> reduce!"a + b + 2"(0, [1,1,1]).writeln; // == 9 as expected
>
> With UFCS I see no elegant way to reduce a chain with a more
> sophisticated reduce argument than the two simple ones listed
> above because the operation is not carried out on the first
> array element, used as the seed. This means:
>
> [1,1,1].reduce!"a + b + 2".writeln; // == 7
>
> which is useless and could easily trip people up because the
> intuitive expectation is that it will act like the seed
> example. If I am wrong in that expectation what is a use case
> for the seedless behaviour?
The fact that it does something different than the seeded version
does not make the seedless version useless - in fact, that's what
makes it useful. A typical use case is to find the maximum of a
range (there is an example of this in the documentation at
http://dlang.org/phobos/std_algorithm.html#reduce). If you don't
know the highest possible value of elements, then you couldn't
come up with an appropriate seed for this case.
I agree that the difference between the two versions of reduce
can be a bit confusing. Maybe it would be better if they were
named differently.
> Is there a way of writing the operation to give the same answer
> as the seed answer?
In general, no (apart from the silly reduce!f(chain([seed],
range))). If you want the behavior of the seeded version, use the
seeded version.
> The element in position 0 should surely have +2 added to
> itself, it's only being the seed out of convenience isn't it?
No, reduce!f(r) is not merely a syntactic sugar for reduce!f(0,
r) (you could say it's a syntactic sugar for reduce!f(r.front,
r.drop(1), though). Making reduce!f(r) be the same as reduce!f(0,
r) doesn't really make any sense - would you expect [1, 2,
3].reduce!"a * b" to return 0? I wouldn't.
> Instead we get 1 + (1 + 2) + (1 + 2). The order of reduce's
> arguments, (seed, range) prevent it being used with UFCS
> properly. If it were (range, seed) then there would be no
> problem:
>
> [1,1,1].reduce!"a + b + 2"(0).writeln; // == 9
This would be better, yes. Reduce was written before there was
UFCS, so they couldn't take this into account. I don't know if it
is possible for this to be changed now, as it would definitely
break some code.
More information about the Digitalmars-d-learn
mailing list