iteration over a string

Jonathan M Davis jmdavisProg at gmx.com
Tue May 28 10:12:13 PDT 2013


On Tuesday, May 28, 2013 03:05:52 Timothee Cour wrote:
> 2A)
> Thanks for your answer;
> 
> You skipped over this one, which I don't understand:
> > string a="ΩΩab";
> > auto b1=a.map!(a=>"<"d~a~">"d).array;
> > writeln(b1);//["<Ω>", "<Ω>", "<a>", "<b>", "", ""]
> > Why are there 2 empty strings at the end? (one per Omega if you vary the
> 
> number of such symbols in the string).
> 
> The above is just weird; is that a bug?

I didn't look into it, since I was in a hurry, but it definitely looks like a 
bug.

> 2B)
> 
> > The reason that we don't do that is mostly because it makes pretty much
> 
> no sense to iterate over ranges of code units 99.99% of the time
> 
> And yet "ΩΩab".map!foo seems to operate on code units and in order to
> operate on code points we need "ΩΩab".stride(1).map!foo, so isn't it
> inconsistent with the fact that std.algorithm.find("ΩΩab") operates on code
> points ?

Any and all range-based functions operate on code points when operating on 
strings. If they do otherwise, it's a bug - probably due to a failed attempt 
to optimize for strings.

> 2C)
> 
> > Remember that ranges don't provide indices unless they're random access,
> 
> For input ranges ranges, I don't understand why the compiler can't accept
> the foreach(i,ai;a) syntax:
> 
> it should behave as follows:
> foreach(i , ai; a){expr}
> 
> rewritten as:
> for(size_t i=0, ai=a.front; !a.empty; a.popFront;){expr}
> 
> but it doesn't compile (it only accepts foreach(ai;a){expr}

foreach and ranges don't do anything with indices. I believe that the reason 
that's usually brought up as to why is that for some types of ranges, it would 
make no sense. There's probably an enhancement request open for it though as 
it would certainly seem to make sense for most ranges. Though if you're 
looking at the counter as being an index, it really doesn't make sense for 
anything other than random-access ranges, as only they have indexing 
operations.

In any case, if you're feeling fancy, you can use iota and zip to solve the 
problem:

 foreach(i, e; zip(iota(0, size_t.max), range))
 {...}

and lockstep uses opApply to add an index, but it doesn't work with just one 
range, so it wouldn't help with just giving foreach an index with normal range 
iteration.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list