How is chunkBy supposed to behave on copy
Steven Schveighoffer
schveiguy at gmail.com
Wed Mar 18 16:18:04 UTC 2020
On 3/18/20 10:57 AM, Dukc wrote:
> ```
> void main()
> { import std;
> auto chunks = [14, 16, 18, 20, 22, 20, 18, 16]
> .chunkBy!((a, b) => a / 10 == b / 10);
>
> //[[14, 16, 18], [20, 22, 20], [18, 16]]
> chunks
> .map!(chunk => chunk.array)
> .array
> .writeln;
>
> //[]
> chunks
> .map!(chunk => chunk.array)
> .array
> .writeln;
> }
> ```
>
> This is how chunkBy[1] currently behaves when copying. It essentially
> behaves like a reference range: it will only save it's state when `save`
> is explicitly called, not otherwise, even if the chunked source range is
> a forward range with value semantics.
>
> As most Phobos ranges preserve the value semantics of their source
> ranges, this is an odd exception, especially as the documentation says
> nothing about it.
>
> So the question is, how should it behave? I have looked at the
> implementation, it should be trivial to have it to use value semantics.
> On the oher hand, someone may rely on the present behaviour.
>
> [1] https://dlang.org/phobos/std_algorithm_iteration.html#.chunkBy
According to the range spec, save must be called if you wish to preserve
state.
In practice, this is seldom done, because most of the time, save just
does `return this;`, so copying works just the same.
The short answer is, use save.
The long answer is, rangeBy uses reference counting internally to store
the range data. I'm not sure why this is, as it seems possible to do
without this mechanism. It seems there is some optimization surrounding
pushing along the range without iterating it twice. But I don't know if
that's a worthwhile optimization, especially if the allocation and
reference counting are more expensive than the iteration.
I would think you could get away with simply storing the range twice,
and using .save to make sure you don't have problems.
-Steve
More information about the Digitalmars-d
mailing list