On Tuesday, 3 July 2012 at 18:00:55 UTC, Jonathan M Davis wrote:
On Tuesday, July 03, 2012 10:40:07 Jonathan M Davis wrote:
On Tuesday, July 03, 2012 17:31:21 Christophe Travert wrote:
> takeFront implementation is dangerous for ranges which
> invalidates their
> front value when popFront is called, for instance,
> File.byLine. Thus
> takeFront will have to be used with care: any range
> implement takeFront
> (because of the template and USFC), but it may not be valid.
> That makes
> the range interface more complicated: There is a takeFront
> property, but
> you have to check it is safe to use... how do you check that
> by the way?
Hmm. I hadn't thought of that. That could be a good reason not
to do this.
I'm not quite sure how to get around that. Hmmm... It would
arguably be a
bit ugly, but a range which couldn't safely be used with
takeFront could
have an enum on it which indicated that, and takeFront would
fail to
compile if used with such a range. Of course, that would mean
that you'd
have to special case such ranges in any range-based function
which used
takeFront so that there was a branch which didn't use
takeFront for ranges
which couldn't use it.
I don't know. It's certainly something to think about. We may
need a
different solution.
An alternative would be to make it so that takeFront (or
consumeFront, as
someone suggested, since that's a better name) would be defined
only for ranges
which it helps. So, similar to hasSlicing, you get something
like hasConsume,
and then a range-based function which wants to use consumeFront
or consumeBack
checks hasConsume!R and uses it on that particular static if
branch if it does
and uses another branch with front and popFront if it doesn't.
std.range.consumeFront then works only with strings (and maybe
arrays).
However, it seemed to me that a major upside of consumeFront as
I proposed it
was that you could always just use it, and it would do the most
efficient thing,
so you _didn't_ have to special case for it, whereas with
hasConsume, you
would. But if you can't use consumeFront safely on all ranges,
then that
doesn't really work. It's still worth something but not as much.
You can already special case strings (and in many cases need
to). What
consumeFront does is make it so that functions operating on
wrappers around
strings (i.e. the results of functions like filter or map) can
operate on them
more efficiently as well. It also makes it so that user-defined
ranges can get
that benefit from algorithms that know nothing about those
ranges and therefore
don't special case them (e.g. std.algorithm functions can then
be more efficient
for user-defined ranges which can define a more efficient
consumeFront). So, even
if we had hasConsume and functions had to special case in order
to use
consumeFront or consumeBack, it would still be beneficial.
However, it would be
nice to have a solution which _didn't_ require special casing.
- Jonathan M Davis
You bet me by 19 seconds and a better explanation :)
So far we have two options: cleaner code because there would be
no need to hack containers which invalidate their front value on
a call to popFront, or a hack which I proposed above, but
localized in such containers. By the way, some of such containers
could potentially defer invalidating front till the next call to
front.