Transience of .front in input vs. forward ranges

H. S. Teoh hsteoh at quickfur.ath.cx
Sun Nov 4 08:16:33 PST 2012


On Sun, Nov 04, 2012 at 08:24:55AM -0500, Andrei Alexandrescu wrote:
> On 11/3/12 7:21 PM, H. S. Teoh wrote:
[...]
> >I wish Andrei would give some input as to how we should proceed with
> >this. I do consider this a major issue with ranges, because for
> >efficiency reasons I often write ranges that have transient .front
> >values, and they can lead to subtle bugs with the current
> >implementation of std.algorithm. It would be good to settle on this
> >issue one way or another. I'd be happy even if the decision is to say
> >that transient ranges are invalid and shouldn't be considered "real"
> >ranges. Anything is better than the current nebulous state of things
> >which only leads to subtle bugs for the unwary.
> 
> I think at this point we should streamline and simplify ranges while
> addressing fundamental concepts (such as unbuffered ranges). Delving
> into defining increasingly niche attributes for ranges is important
> work, but to the extent we can make things simpler that would be a
> gain.
> 
> In my view, transiency of .front has a lot to do with input ranges.
> An input range means that .front is evanescent upon calling
> .popBack; it has no lasting presence in memory, and invoking popBack
> means the next item will replace the current one.
> 
> Fetching lines should be solved by using types; trafficking in
> char[] does not offer guarantees about the preservation of the
> content. In contrast, trafficking in string formalizes a binding
> agreement between the range and its user that the content is
> immutable.
[...]

I think that this may be oversimplifying the issue. What about the
example of a range of in-place permutations over an array? That range
can be made a forward range, or even bidirectional (by reversing the
sense of the comparison used by nextPermutation). But it is inherently a
transient range.

And this is merely one example. I have some non-trivial code that
evaluates an expression tree, each node of which may generate multiple
elements; one may take a range over all possible values that the tree
may have. For efficiency reasons, each output value (which is
vector-valued) reuses the same buffer. It is a forward range with a
transient .front (it has to be a forward range, because otherwise one
can't range over all combinations of multiple values that subtrees may
produce).

While I'm perfectly fine with the decision that such ranges shouldn't be
considered proper ranges at all, it would greatly limit the
applicability of std.algorithm in my code. Either I would have to
artificially limit the range to an input range (which is a bit silly, as
it amounts to renaming .save to something else just so std.algorithm
wouldn't recognize it as a forward range), or I wouldn't be able to use
std.algorithm to manipulate these ranges, but would have to roll my own.
Of course, D makes it so that rolling my own isn't all that hard, but it
would be a bit disappointing that the supposedly-generic algorithms in
the standard library aren't that generic after all.


T

-- 
I see that you JS got Bach.


More information about the Digitalmars-d mailing list