std.algorithm.joiner unexpected behavior

Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Aug 31 16:37:20 PDT 2017


On Thursday, August 31, 2017 14:09:55 H. S. Teoh via Digitalmars-d-learn 
wrote:
> On Thu, Aug 31, 2017 at 01:34:39PM -0600, Jonathan M Davis via
> Digitalmars-d-learn wrote: [...]
>
> > In general, byLine does not work with other range-based algorithms
> > precisely because it reuses the buffer. I think that it does manage to
> > work for some, but IMHO, it should have just supported foreach via
> > opApply and not been a range at all. It's great for efficiency in a
> > loop but horrible for range chaining.
>
> [...]
>
> Transient ranges are tricky to work with, I agree, but I don't agree
> that they're "horrible for range chaining".  I argue that many range
> algorithms that assume the persistence of .front are inherently wrong,
> and ought to be implemented in a way that does *not* make this
> assumption.  Many std.algorithm algorithms *can* in fact be written in
> this way, and those that aren't, are arguably buggy.
>
> For example, some std.algorithm functions take a forward range but then
> tries to save .front to a local variable. Rather, they should use .save
> to save the previous position of the range so that they can call .front
> on that to access the previous element, instead of making the unfounded
> assumption that whatever the local variable refers to will still remain
> valid after calling .popFront.  It's just sloppy coding IMNSHO.

I know. We've had this argument before. Personally, I think that the range
spec should require that front _not_ be transient and that any ranges that
are be considered non-conformant. Yes, under some set of circumstances, they
can be made to work, but IMHO, it's simply not worth it. As it is, simply
calling save when it's supposed to be called gets totally botched all the
time even if ranges with transient front aren't involved. And adding such
ranges just makes it too complicated. What we have currently with the range
API allows for a lot of stuff to work correctly as long as certain
assumptions are bet, but as soon as folks start doing stuff that doesn't
behave the same way that a dynamic array does, things start falling apart.
Even copying ranges in generic code does not have defined behavior, because
different types have different semantics even if they follow the range API
and pass isInputRange, isForwardRange, etc. The status quo works well enough
that we get by, but it's a mess when you get into the details - especially
if you want code that's actually generic. And IMHO, trying to add ranges
with a transient front into the mix is taking it way to far. It's simply not
worth it. But I know that you don't agree with that.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list