DMD Bug or not? foreach over struct range
Jonathan M Davis
jmdavisProg at gmx.com
Wed May 16 00:40:54 PDT 2012
On Wednesday, May 16, 2012 09:24:23 Era Scarecrow wrote:
> On Wednesday, 16 May 2012 at 07:04:09 UTC, Jonathan M Davis wrote:
> > that assertion would pass, but it doesn't, and it shouldn't. If
> > your range was a reference type (e.g. if it were a class or it
> > was like the ranges in std.stdio which deal with I/O), then
> > using it with foreach would consume it, but that won't happen
> > with a value type range.
>
> Then perhaps I'm missing something. Some time ago (6 months?) I
> submitted a similar example of this to walter; a little prime
> walking range-like struct that acts like a range. It may contain
> an AA, but otherwise basic structure isn't far from his...
>
> Could you explain why mine works and his doesn't? (Extras taken
> out proving ever number is a prime)
>
> ---
> import std.stdio;
>
> struct prime_walk {
> int map[int];
> int position = 2;
> int cap = int.max;
>
> int front() {
> return position;
> }
>
> void popFront() {
> //where the real work is done.
>
> if ((position & 1) == 0) {
> position++;
> } else if (position >= cap) {
> throw new Exception("Out of bounds!");
> } else {
> int div = position;
> int p2 = position * 3;
>
> //current spot IS a prime. So...
> if (p2 < cap)
> map[p2] = div;
>
> position += 2;
>
> //identify marked spot, if so we loop again.
> while (position in map) {
> div = map[position];
> map.remove(position);
> p2 = position;
> do
> p2 += div * 2;
> while (p2 in map);
>
> position += 2;
> if (p2 <= cap) //skip out, no need to save larger than
> needed values.
> map[p2] = div;
> }
> }
> }
>
> bool empty() {
> return position >= cap;
> }
> }
>
> void main() {
> prime_walk pw;
> pw.cap = 100;
> foreach(i; pw)
> writeln(i);
> }
I'm not quite sure what yours is doing, but yours isn't empty after the call
to foreach any more than Nick's is. The issue with Nick's is that he's using
the original range _inside_ the loop and not seeing the changes. Your loop
isn't referencing the original range. It just uses its copy. If you did
void main()
{
prime_walk pw;
pw.cap = 100;
foreach(i; pw)
writefln("%s %s", i, pw.position);
}
You'd see that pw.postion is always printed as 2, just like Nick's foo.val
always prints as 0.
- Jonathan M Davis
More information about the Digitalmars-d-learn
mailing list