joiner: How to iterate over immutable ranges?
Ali Çehreli via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Sun Feb 14 17:14:10 PST 2016
On 02/14/2016 11:32 AM, Bastiaan Veelo wrote:
> Thanks. I didn't know that iterating a range means mutating its
> contents.
That's not the case: Just like an iterator, a range must maintain some
state to know which item is next. What needs to be mutated is that
iteration state.
> I still don't quite get it, and it is probably because I don't
> fully understand ranges. I think what confuses me the most is their
> analogy to containers.
Yes, that analogy is the wrong one (and D's slices (or dynamic arrays)
don't help with that).
> It's no problem to iterate over a container of immutable data, but
> it is for a range.
Not true. You can iterate over immutable data. In fact, a string is
nothing but a container of immutable characters yet we can iterate over it.
> I thought that joiner provided a contiguous view on distinct ranges,
> without needing to touch these. Is there another method to traverse a
> range of ranges without making copies or mutation?
Not without making copies but note that the copy that you need to make
is just the slices (i.e. views into data), which consist of just a
length and a pointer fields. If it's acceptable for you, the following
code calls .save on the elements and it works:
import std.algorithm.iteration;
import std.stdio;
import std.array; // <-- ADDED
void main()
{
immutable(string[])[] icycles;
icycles ~= ["one", "two"];
icycles ~= ["three", "four"];
foreach (number; icycles.map!(r => r.save).joiner)
writeln(number);
}
Again, .save on an array is cheap. What will happen is that the original
immutable arrays will be untouched but their proxies returned by .save
will be consumed.
Ali
More information about the Digitalmars-d-learn
mailing list