On 11/20/2015 11:34 AM, Sönke Ludwig wrote:
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.

(had this in my other's laptop outbox for a while)

The baseline was STL's input iterators, which were quite bad - there's no syntactic distinction between input and forward iterators, which makes the entire matter a convention. That's not the case for any other iterators - code using their capabilities won't compile with weaker iterators (nice).

So initially I thought a simple solution would be this:

struct MyForwardRange
{
    enum bool isForward = true;
    ... empty, front, popFront ...
}

enum isForwardRange(R) =
  is(typeof(R.isForward)) && R.isForward;

Then there's no need for .save(), and isForward!R can be used for constraints etc. Reference forward ranges are not supported but then that's liberating (fewer complications), rare, and easy to work around by wrapping.

Looking back, the only reason for which I didn't go that way was fear; I simply hadn't seen such an idiom and I was afraid it'd be too nonconformist. Introspection was new and back then quite arcane, and the idioms were unclear. So I went with a more conventional solution of adding one method.

Today that's the way I'd do it, and in fact it is the way the new collections will work exactly that way - if a type exposes isStdCollection then it commits to implementing the collection primitives as specified.

As of right now the situation with ranges is suboptimal - you need to use .save() but if you don't the sheer copy works most of the time, just not always. It may be nice to improve on that a bit, for example to require input ranges that are not forward ranges to indeed have reference semantics. Or require forward ranges to define .save() but only with the body { return this; }. Either of these would break code.


Andrei

  • range.save Freddy via Digitalmars-d
    • Re: range.save Rikki Cattermole via Digitalmars-d
    • Re: range.save Sönke Ludwig via Digitalmars-d
      • Re: range.save Andrei Alexandrescu via Digitalmars-d
        • Re: range.save Sönke Ludwig via Digitalmars-d
          • Re: range.save Jonathan M Davis via Digitalmars-d
          • Re: range.save Andrei Alexandrescu via Digitalmars-d
            • Re: range.... Jonathan M Davis via Digitalmars-d
            • Re: range.... Joseph Rushton Wakeling via Digitalmars-d
              • Re: ra... Jonathan M Davis via Digitalmars-d
                • Re... Joseph Rushton Wakeling via Digitalmars-d
                • Re... Jonathan M Davis via Digitalmars-d
                • Re... Jonathan M Davis via Digitalmars-d
                • Re... Joseph Rushton Wakeling via Digitalmars-d
                • Re... Jonathan M Davis via Digitalmars-d
                • Re... Joseph Rushton Wakeling via Digitalmars-d
                • Re... Jonathan M Davis via Digitalmars-d

Reply via email to