Transience of .front in input vs. forward ranges

Jonathan M Davis jmdavisProg at gmx.com
Mon Nov 5 23:17:08 PST 2012


On Tuesday, November 06, 2012 08:49:26 Andrei Alexandrescu wrote:
> On 11/6/12 4:36 AM, H. S. Teoh wrote:
> > Hmm. Another idea just occurred to me. The basic problem here is that we
> > are conflating two kinds of values, transient and persistent, under a
> > single name .front. What if we explicitly name them? Say, .copyFront for
> > the non-transient value and .refFront for the transient value (the
> > names are unimportant right now, let's consider the semantics of it).
> 
> We could transfer that matter to the type of .front itself, i.e. define
> a function copy(x) that returns e.g. x for for string and x.dup for
> char[] etc. There would be problems on e.g. defining copy for structs
> with pointer and class reference fields etc.
> 
> One quite simple approach would be to define (on the contrary)
> .peekFront, which means "yeah, I'd like to take a peek at the front but
> I don't plan to store it anywhere". That would entail we define eachLine
> etc. to return string from .front and char[] from .peekFront, and
> deprecate byLine.

peekFront would work better than copy, because whether front needs to be 
copied or not doesn't necessarily have much to do with its type. For instance, 
byLine/eachLine can return char[] from front just fine and still have it be a 
new array every time. So, while in some cases, you can tell from the type that 
no copy is needed (e.g. string), you can't tell in the general case and would 
be forced to make needless copies in a number of cases. For instance, every 
range of class objects would end up having to make a copy, because they'd be 
mutable reference types, and without knowing that the range is doing, you have 
no way of knowing whether it keeps replacing the objects referred to by front 
or not (it's not particularly likely that it would be, but you can't tell for 
sure just the same).

If we defined peekFront via UFCS as a wrapper which calls front, then anything 
wanting to use peekFront could use peekFront regardless of whether the type 
defined it or not. So, that would reduce the impact caused by its introduction, 
but it would still impact a lot of range types ultimately, because we'd have 
to create appropriate wrappers for peekFront in most of them, or we'd end up 
making unnecessary copies.

I don't like how much this impacts, but as H. S. Teoh points out, we don't 
exactly have very many options with minimal impact beyond banning transient 
fronts entirely (which I'd honestly like to do just the same).

At least this avoids the need to create more traits to test ranges for, since 
if we create a free function peekFront, all range types can just assume that 
it's there and create wrappers for it without caring whether the wrapped range 
defines it itself or uses the free function. And it's less complicated than the 
.transient suggestion. Though it _does_ introduce the possibility of front and 
peekFront returning completely different types, which could complicate things a 
bit. It might be better to require that they be identical to avoid that 
problem.

For better or worse though, this approach would mean that byLine (or eachLine 
or whatever) wouldn't be reusing the buffer with foreach like they do now, 
though I suppose that you could make them have opApply which does the same 
thing as now (meaning that it effectively uses peekFront), and then any range-
based functions would use front until they were updated to use peekFront if 
appropriate. But then again, maybe we want byLine/eachLine to copy by default, 
since that's safer, much as it's less efficient, since then we have safe by 
default but still have an explicit means to be more efficient. That fits in well 
with our general approach.

peekFront may be the way to go, but I think that we need to think through the 
consequences (like the potential problems caused by front and peekFront 
returning different types) before we decide on this.

- Jonathan M Davis


More information about the Digitalmars-d mailing list