range.save
Sönke Ludwig via Digitalmars-d
digitalmars-d at puremagic.com
Fri Nov 20 08:34:59 PST 2015
Am 20.11.2015 um 16:37 schrieb Andrei Alexandrescu:
> On 11/20/2015 04:42 AM, Sönke Ludwig wrote:
>> I think that .save is a serious design flaw in the range API
>
> How would you redo it? -- Andrei
That's why I wrote that the alternatives had their own issues - I
unfortunately don't have a solution to this either. Making usage errors
fail loudly at runtime is the only one improvement I had in mind that
wouldn't result in unacceptable code breakage.
Now if we could exclude reference type ranges from the picture* and
ignore the fact that this would break tons of code, I think making input
ranges non-copyable and using the postblit constructor to do the job of
save() would be the right approach. Recently this was mentioned
somewhere and the counter argument was that this wouldn't work for
wrapper ranges:
struct FilterRange(R) {
private R _input;
this(R input) {
_input = input; // error: R not copyable
}
// ...
}
But it does work!
struct FilterRange(R) {
private R _input;
this(R input) {
swap(_input, input); // fine!
}
// ...
}
Passing a range into such a wrapper range can still be done directly in
case of rvalues: FilterRange!MyRange(MyRange(...))
L-values require an explicit "move" call (which is a good thing):
MyRange r;
auto fr = FilterRange(r.move);
The lowering of "foreach" to "for" would also have to be adjusted
accordingly.
The main drawback of using postblit for forward ranges is that it might
happen that it gets invoked accidentally, resulting in hidden
performance issues (IMO better than correctness issues, but anyway).
That could either be mitigated by performing substantial work lazily
instead of directly in this(this), or by keeping support for save() in
addition to this(this), so that a valid forward range could still
disable this(this) if it's costly and expose the copy functionality
through save() instead.
* To still support reference type ranges, we could turn this around and
define a copyref() method that creates a new range that references the
same internal range object. The advantage is that this way around
failure to call copyref() will result in an immediate error.
More information about the Digitalmars-d
mailing list