Transience of .front in input vs. forward ranges
Jonathan M Davis
jmdavisProg at gmx.com
Mon Nov 5 17:03:45 PST 2012
On Monday, November 05, 2012 16:49:42 H. S. Teoh wrote:
> On Mon, Nov 05, 2012 at 11:51:35PM +0200, Andrei Alexandrescu wrote:
> [...]
>
> > >With Andrei's proposal, all code that assumes transient .front with
> > >input ranges are broken by definition.
> >
> > I think this should be: all code that DOES NOT assume transient
> > .front with input ranges is broken.
>
> Then std.array.array is broken by definition, and cannot be implemented
> with anything less than a forward range. This will very likely break a
> lot of existing code.
We can create an hasTransientFront trait for checking whether front is
transient or not. It can't be 100% accurate, but it would fall on the side of
declaring something transient when it wasn't, so it wouldn't declare something
transient to be non-transient. Then any range for which hasTransientFront was
false could work with std.array.array. For the rest, they can do something
like
auto arr = std.array.array(map!"a.dup"(file.byLine()));
But it's certainly true that fixing std.array.array will break code, which is
annoying. But as long as front can be transient, there's no way around that.
byLine cannot possibly work with std.array.array as it stands. The only
solutions that I see at this point are
1. Exclude transience completely.
2. Mark ranges as transient in some way and force algorithms to take this new
trait into account.
3. Insist that input ranges have transient fronts (save perhaps when it can be
statically verified that they aren't based on front's type) and that anything
requiring a non-transient front require forward ranges.
4. Make all ranges non-transient but provide a way to get at a transient
version of it and force algorithms to take this new property into account.
All 4 solutions have problems. They just have different problems.
> I still think forcing input ranges to be transient is oversimplifying
> the issue. Whether a range is transient is orthogonal to whether you can
> .save the current position or whether you can traverse it in two
> directions. Trying to conflate the two only leads to leaky abstractions.
I completly agree that transience and whether something is an input range are
orthogonal, but we need to simplify.
> The only real solution IMO is to address the issue head-on: either
> recognize transience as an inherent property of ranges, or (re)define
> ranges to exclude all transience.
Personally, I'm all for excluding transience completely and insisting that
anything which would be transient use opApply, but Andrei doesn't like that
idea. It would certainly be the simplest solution though, and it probably
wouldn't really cause much of a problem for ranges like ByLine, because in
most cases what you do is use them with a foreach loop. std.array.array would
be the main loss there, but if opApply is used for foreach rather than the
range functions (I don't know which currently gets precedence), then ByLine
can become a normal range when used with range functions (i.e. no transience)
and just reuse its buffer with opApply. Then it would work with range-based
functions but still avoid extra allocations when simply iterating over it.
That would be my ideal solution at this point, but clearly not everyone
agrees.
- Jonathan M Davis
More information about the Digitalmars-d
mailing list