http://d.puremagic.com/issues/show_bug.cgi?id=4705



--- Comment #10 from bearophile_h...@eml.cc 2011-05-23 16:12:53 PDT ---
The code that uses minPos() also leads to a possible bug (a real bug I have
found in my code), shown here:


import std.stdio, std.algorithm, std.math, std.range, std.random;
int gen(int x) { return uniform(-100, 100); }
void main() {
    auto data = map!gen(iota(10));
    writeln(data);
    writeln(data);
    int result = minPos!((a, b){ return abs(a) < abs(b); })(data).front();
    writeln(result);
}


The output shows that gen is recomputed every time data is used, so
abs(a)<abs(b) gives bogus results:
[-87, -1, 86, -93, -89, 16, 17, -91, 55, 88]
[-36, 91, 38, 6, 23, 85, 60, -25, -48, -100]
-97

(Maybe I'd like an annotation to tell the compiler that "data" is an an Input
Range, unlike iota() that map is iterating on.)


To avoid that bug you have to turn data into an array:

import std.stdio, std.algorithm, std.math, std.range, std.random;
int gen(int x) { return uniform(-100, 100); }
void main() {
    auto data = array(map!gen(iota(10)));
    writeln(data);
    writeln(data);
    int result = minPos!((a, b){ return abs(a) < abs(b); })(data).front();
    writeln(result);
}


Now abs(a)<abs(b) gets computed on something that's not changing under the
carpet, and there is no bug:
[-41, -36, -15, -35, 91, 31, -5, -67, -91, -65]
[-41, -36, -15, -35, 91, 31, -5, -67, -91, -65]
-5



In code like this there is no need to turn data into an array, the result is
correct even keeping "data" lazy because items of data are accessed only once
to compute abs(a):


import std.stdio, std.algorithm, std.math, std.range, std.random;
int gen(int x) { return uniform(-100, 100); }
void main() {
    auto data = map!gen(iota(10));
    int result = min!q{ abs(a) }(data);
    writeln(result);
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------

Reply via email to