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.