March 28, 2019
On 3/28/19 4:52 AM, Walter Bright wrote:
> A topical example:
> 
> https://github.com/dlang/phobos/pull/6346#issuecomment-477504005

See also the related issue: https://issues.dlang.org/show_bug.cgi?id=18657

Indeed so, thanks. The entire thing with ranges whereby save() does something else than a mere copy has been a mistake and supporting it has been an expensive distraction.

The intent of save() was as a mere flag to signal that the range is a forward range and not an input range. It should have been a simpler policy - e.g. ranges that advertise being forward ranges would define this inside:

enum bool isForward = true;

Ranges should have one of two categories:

* for input ranges, all copies share and advance the same underlying position;

* for forward ranges, each copy holds its own position.

Anything else is not a range.

There's a lot of good stuff in Phobos, and then there's a lot of fat added to support an ill-intended notion of generality.
March 28, 2019
On 3/28/19 7:02 AM, ag0aep6g wrote:
> On 28.03.19 09:52, Walter Bright wrote:
>> A topical example:
>>
>> https://github.com/dlang/phobos/pull/6346#issuecomment-477504005
> 
> That pull request was open for a year(!) waiting for someone to make a decision. And before that I had asked about the issue on the forum [1].
> 
> If you want things to go your way, consider answering when someone asks for direction.

That's good work actually (which underlines the irony of the situation) - once refRange got in the question of supporting it came naturally. Generality crept in, one good intention at a time.

We should use D's good name lookup mechanism to create a versioning strategy a la std.v2 that reuses the good parts of std and fixes the bad parts. That way we focus on adding good things and letting bad things in maintenance mode, as opposed to changing existing things. Even C++, with its rather poor modularity mechanism, has made std::tr1 and std::tr2 work.
March 28, 2019
On 28.03.19 12:02, ag0aep6g wrote:
> By the way, I didn't get an email notification from GitHub for that comment.

Scratch that, it arrived. Just took a couple of hours.
March 28, 2019
On 28.03.19 12:12, Andrei Alexandrescu wrote:
> See also the related issue: https://issues.dlang.org/show_bug.cgi?id=18657
> 
> Indeed so, thanks. The entire thing with ranges whereby save() does something else than a mere copy has been a mistake and supporting it has been an expensive distraction.

`save` is a red herring with regards to issue 18657.

The problem isn't RefRange.save, it's RefRange.opAssign. The issue manifests often in implementations of `save`, but that's just because they *assign* the result of `save` over an existing range.

Note that there's no `save` call in issue 18657's third example (`choose`).

The question is whether ranges are allowed to implement opAssign like RefRange does. If so, all of Phobos needs fixing to avoid calling opAssign. If not, RefRange.opAssign should be removed.
March 28, 2019
On 3/28/19 7:45 AM, ag0aep6g wrote:
> On 28.03.19 12:12, Andrei Alexandrescu wrote:
>> See also the related issue: https://issues.dlang.org/show_bug.cgi?id=18657
>>
>> Indeed so, thanks. The entire thing with ranges whereby save() does something else than a mere copy has been a mistake and supporting it has been an expensive distraction.
> 
> `save` is a red herring with regards to issue 18657.
> 
> The problem isn't RefRange.save, it's RefRange.opAssign.

The problem is RefRange.
March 28, 2019
On 28.03.19 12:51, Andrei Alexandrescu wrote:
> The problem is RefRange.

too terse
March 28, 2019
On 3/28/19 7:59 AM, ag0aep6g wrote:
> On 28.03.19 12:51, Andrei Alexandrescu wrote:
>> The problem is RefRange.
> 
> too terse

Reasoning from first principles would go as follows. Context: algorithms are expressed naturally in terms of ranges, and composite (higher-order) ranges are built and work with ranges. Event: RefRange comes along, exposes an oddity ("save(), copying, and assignment could do slightly different things"), breaks a bunch of these structures, and requires arcane changes.

The conclusion is not to operate such changes everywhere (i.e. reason by analogy). The right conclusion is that save() is unnecessarily general and underspecified.

March 28, 2019
On 3/28/19 8:37 AM, Andrei Alexandrescu wrote:
> On 3/28/19 7:59 AM, ag0aep6g wrote:
>> On 28.03.19 12:51, Andrei Alexandrescu wrote:
>>> The problem is RefRange.
>>
>> too terse
> 
> Reasoning from first principles would go as follows. Context: algorithms are expressed naturally in terms of ranges, and composite (higher-order) ranges are built and work with ranges. Event: RefRange comes along, exposes an oddity ("save(), copying, and assignment could do slightly different things"), breaks a bunch of these structures, and requires arcane changes.
> 
> The conclusion is not to operate such changes everywhere (i.e. reason by analogy). The right conclusion is that save() is unnecessarily general and underspecified.

Similar issues:

"People may attempt to use Phobos algorithms with ranges of enums based on character types, or other subtypes of character types." Reasoning by analogy: those should work, too. Leads to generality creep. Reasoning from first principles: UTF8 is predicated on one byte type, no real gain to be made.

"There are several ways of iterating strings, e.g. by code point, by code unit, or by grapheme." Reasoning by analogy: strings should be ranges, hence we need to choose one default mode of iteration. Reasoning from first principles: strings are wholes, not ranges, and iteration is chosen as needed.

"There are UTF8, UTF16, and UTF32 encodings." Reasoning by analogy: they should all work the same. Reasoning from first principles: what's really needed here? Realistically nobody uses UTF32, UTF16 is an evolutionary dead-end still alive mostly as a mild annoyance on Windows systems, and then everybody and their cat is using UTF8. It follows we should consolidate on one encapsulated string type that is NOT an array (because arrays are ranges) and that offers iteration modes on demand. All that gobbledygook with e.g. file and path functions supporting lazy ranges of characters should go. It's an unnecessary and expensive to maintain distraction.

March 28, 2019
On 28.03.19 13:37, Andrei Alexandrescu wrote:
> The conclusion is not to operate such changes everywhere (i.e. reason by analogy). The right conclusion is that save() is unnecessarily general and underspecified.

If you want to resolve the issue by amending the definition of ranges, that's very fine with me. I'd much prefer that solution over going through all of Phobos.

But if you focus on `save`, you're missing the point of issue 18657, which is opAssign. A range can have a misbehaving opAssign without being a forward range.
March 28, 2019
On 3/28/19 9:04 AM, ag0aep6g wrote:
> On 28.03.19 13:37, Andrei Alexandrescu wrote:
>> The conclusion is not to operate such changes everywhere (i.e. reason by analogy). The right conclusion is that save() is unnecessarily general and underspecified.
> 
> If you want to resolve the issue by amending the definition of ranges, that's very fine with me. I'd much prefer that solution over going through all of Phobos.
> 
> But if you focus on `save`, you're missing the point of issue 18657, which is opAssign. A range can have a misbehaving opAssign without being a forward range.

Then some ranges are not meant to be assignable.