range.save
Andrei Alexandrescu via Digitalmars-d
digitalmars-d at puremagic.com
Thu Nov 26 09:23:07 PST 2015
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
More information about the Digitalmars-d
mailing list