protocol for using InputRanges

Steven Schveighoffer schveiguy at yahoo.com
Mon Mar 31 04:40:11 PDT 2014


On Sat, 29 Mar 2014 17:02:30 -0400, Marc Schütz <schuetzm at gmx.net> wrote:

> On Saturday, 29 March 2014 at 01:36:46 UTC, Steven Schveighoffer wrote:
>> On Fri, 28 Mar 2014 07:47:22 -0400, Marc Schütz <schuetzm at gmx.net>  
>> wrote:
>>> On Thursday, 27 March 2014 at 16:12:36 UTC, monarch_dodra wrote:
>>>> If you initialized the next element in both constructor and popFront,  
>>>> then you'd get rid of both these checks.
>>>>
>>>
>>> ... but of course lose laziness.
>>
>> In this case, laziness is not critical. Decoding the element is an O(1)  
>> operation, and when looping through, you will decode it anyway.
>>
>> When processing a 20 element string, the cost of checking to see if you  
>> have decoded on every empty or front call may override the front-loaded  
>> cost of decoding the first element on construction. It's sure to add to  
>> the cost if you are processing all 20 elements, since you decode them  
>> all anyway.
>>
>> On other ranges, it's more important when the first element costs a lot  
>> to fetch. HOWEVER, it's not critically important to delay that unless  
>> you are not going to process that element. For example, if you are  
>> foreach'ing over all the elements, the delay doesn't matter.
>>
>> I'd rather the higher level code decide whether to delay or not,  
>> depending on the situation. Requiring a protocol change for such  
>> detailed knowledge seems unbalanced.
>
> I was more thinking of the fact that you need to read something on  
> construction, rather than on consumption, and this reading might be  
> noticeable. There was the example of `stdin.byLine().filter(...)` (or  
> something similar, don't remember exactly), which reads from stdin on  
> construction. This changes the behaviour of the program, because the  
> read operation will (probably) block.

Blocking operations may have a noticeable impact, but they may not. It  
depends on what you do between construction and processing.

For example, if you have:

foreach(l; stdin.byLine)

Lazily fetching the first line makes no operational difference whatsoever,  
even if it blocks, because you're immediately going to process it.

But if it *is* lazily fetched, you are paying some possibly small, but  
nonzero, cost for that laziness that you didn't need to pay.

This is why I said it's not critically important to delay unless you are  
not going to process the first element. Because there is no primitive to  
"prime" the range, we must do it on a property fetch, or on construction.  
But after that, popFront is a perfectly reasonable place to get the next  
element.

All this fuss is over the *first* element in the range. I think providing  
a mechanism to decide whether you want it now or later is reasonable. For  
example a lazy range wrapper.

Note, however, the case Andrei was arguing about was one of the string  
decoders. When you are blocking for input, hell, even if you aren't  
blocking, but need to call system calls to get it, the performance cost of  
checking a boolean every call is negligible. But when you are decoding 1-4  
bytes of data in memory, checking a boolean becomes significant.

-Steve


More information about the Digitalmars-d mailing list