Transience of .front in input vs. forward ranges

H. S. Teoh hsteoh at quickfur.ath.cx
Tue Nov 6 08:12:08 PST 2012


On Mon, Nov 05, 2012 at 11:17:08PM -0800, Jonathan M Davis wrote:
> 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.

I like .peekFront. It's easy to understand, and is self-documenting. And
this approach is safe by default (all current code uses .front), and can
be implemented incrementally (doesn't require updating all of Phobos at
once to avoid transience-related bugs in the interim).


> 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.

Yeah, I think trying to guess transience from the return type is risky,
and prone to bugs. OTOH, having a generic language-wide way to duplicate
a value is something worth considering. I think it will allow us to
solve a number of other nagging issues.


[...]
> 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.

The free function can be made to always conform to the same type as
.front:

	ElementType!R peekFront(R)(R range) { return range.front; }

Though it still doesn't prevent a member called .peekFront of a
different type. We *could* use template constraints to enforce that
though:

	auto myRangeFunc(R)(R range)
		if (is(typeof(range.front)==typeof(range.peekFront)))
	...

This could be put in a template that the other range-checking templates
can call.


> 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.

I think we should make byLine copy by default. Only if you explicitly
call peekFront you get the non-copying behaviour. This fits better with
D's motto of being safe by default, and fast if you know what you're
doing.


> 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.
[...]

For simplicity, I think we should just enforce typeof(.front) ==
typeof(.peekFront). We will get needless complications otherwise.


T

-- 
We've all heard that a million monkeys banging on a million typewriters
will eventually reproduce the entire works of Shakespeare.  Now, thanks
to the Internet, we know this is not true. -- Robert Wilensk


More information about the Digitalmars-d mailing list