Functional vs simple code
ixid
nuaccount at gmail.com
Tue Oct 2 18:21:47 PDT 2012
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
More information about the Digitalmars-d-learn
mailing list