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