Proposal: takeFront and takeBack

deadalnix deadalnix at gmail.com
Wed Jul 4 09:49:38 PDT 2012


Le 04/07/2012 17:17, Andrei Alexandrescu a écrit :
> On 7/4/12 8:33 AM, deadalnix wrote:
>> Le 04/07/2012 13:04, Roman D. Boiko a écrit :
>>> On Wednesday, 4 July 2012 at 10:54:41 UTC, deadalnix wrote:
>>>> I do agree with that. However, the current proposal have the same
>>>> drawback but on the code that use the range.
>>>>
>>>> Both solutions are messy IMO.
>>>
>>> What is error-prone in current client code?
>>>
>>> If particular algorithm wants to take advantage of a potential speed-up,
>>> it may decide to check whether hasConsume!Range, and call consumeFront
>>> instead of front + popFront. Nobody is obliged to do so.
>>>
>>> The only problem I can see is potential code duplication, which is lower
>>> priority in performance-critical part of code, IMO.
>>>
>>
>> You have to maintain 2 version of you algorithm. This is more work to
>> test, to maintain, and it is likely to introduce more bugs.
>>
>> More code == more bugs. More NPATH = more bugs and harder to test and to
>> maintain.
>>
>> In addition, this will result in practice in less generic code, because
>> one may not need the version of the algorithm without consume primitives
>> in his/her own code and not code it at all.
>
> I agree. Can't get behind this proposal.
>
> First, it solves the problem of double decoding for UTF-8 and UTF-16
> strings. Before that, we need to estimate how bad the problem is and how
> we can optimize front/popFront() to alleviate it. For all I can tell, in
> ASCII-heavy strings we're looking at optimizing away ONE redundant
> comparison in a sequence that involves a bounds check, two word
> assignments, and another comparison. Off the top of my head I don't
> think the gains are going to be impressive.
>
> Looking at the current implementation in std.array:
>
> void popFront(A)(ref A a)
> if (isNarrowString!A && isMutable!A && !isStaticArray!A)
> {
> assert(a.length, "Attempting to popFront() past the end of an array of "
> ~ typeof(a[0]).stringof);
> a = a[std.utf.stride(a, 0) .. $];
> }
>
> So here we have a bounds check, a call to stride, and two word
> assignments. The implementation of stride itself is:
>
> uint stride(S)(in S str, size_t index) @safe pure
> if (is(S : const(char[])))
> {
> immutable c = str[index];
> if (c < 0x80)
> return 1;
> else
> return strideImpl(c, index);
> }
>
> Here, even if we assume stride is inlined, we have one redundant bounds
> check that we can avoid, and redundant operations with "index" which is
> always 0.
>
> In theory all of these redundant operations can be done away with
> optimization techniques, but probably some aren't. So we should look
> first at optimizing this flow heavily before looking at an API addition
> that has disadvantages in other dimensions.
>
>
> Andrei

Some were talking about popFront returning the front element.

Can you enlight us on why front/popFront dichotomy ? It seems to me that 
the popFront only solution is the best one (it solve the byLine 
problem). Maybe they are some other issue we didn't considered here, so 
I'd be happy to know why it have been done that way in the first place.

However, this is something we shouldn't consider now because of the 
breaking change it introduce anyway.


More information about the Digitalmars-d mailing list