Proposal: takeFront and takeBack
Roman D. Boiko
rb at d-coding.com
Tue Jul 3 11:06:19 PDT 2012
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.
More information about the Digitalmars-d
mailing list