On Tuesday, 2 October 2012 at 22:13:10 UTC, Timon Gehr wrote:
On 10/03/2012 12:11 AM, Timon Gehr wrote:
...

$ cat ixidbench.d
module main;
import std.stdio, std.algorithm, std.range, std.datetime;

enum MAX = 10_000_000_000UL;

void main() {
    StopWatch sw;
    sw.start;

    auto sum1 = MAX.iota.map!(x => x * x).reduce!"a + b";

    sw.stop;
    sw.peek.msecs.writeln("msecs");
    sum1.writeln;
    sw.reset;
    sw.start;

    ulong sum2 = 0;
    foreach(i;0..MAX)
        sum2 += i * i;

    sw.stop;
    sw.peek.msecs.writeln("msecs");

    sum2.writeln;
}
$ ldmd2 -O -release -inline ixidbench.d -ofixidbench
$ ./ixidbench
6528msecs
7032546979563742720
7518msecs
7032546979563742720

$ gdmd -O -release -inline ixidbench.d -ofixidbench
$ ./ixidbench
11250msecs
7032546979563742720
11233msecs
7032546979563742720

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? Is there a way of writing the operation to give the same answer as the seed answer?

The element in position 0 should surely have +2 added to itself, it's only being the seed out of convenience isn't it? 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

Reply via email to