March 27, 2014 Re: protocol for using InputRanges | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Thu, 27 Mar 2014 16:58:12 -0400, Walter Bright <newshound2@digitalmars.com> wrote:
> On 3/27/2014 12:50 PM, Andrei Alexandrescu wrote:
>> Yah, agreed. -- Andrei
>
> Completely unworkable. To determine if a range is empty or not, it may have to actually read from its input. TTYs are an example. Although empty may then cache the result, and not read the second time it is called, an observer of TTY could see that an item was read from the TTY.
In the land of ranges, it's construction and popFront that generally advances the range. Empty does not. This is why assert(!empty) is all over the place, it's considered to be non-destructive.
Note that a stream makes a terrible range, simply because of what you say -- reading is destructive, and determining emptiness is dependent on reading. You need a buffered stream to make a good range, and then the logic becomes much more straightforward.
The awkwardness for shoehorning streams into ranges I see is that the advancement (popFront) and the check for termination (empty) are decoupled, when in reality they are synced for a stream. This REQUIRES a sticky bit for popFront to communicate with empty on whether it is EOF or not.
Even a single byte buffer is not enough, you need a bool to indicate the stream is done.
-Steve
|
March 27, 2014 Re: protocol for using InputRanges | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Thu, 27 Mar 2014 17:06:35 -0400, Walter Bright <newshound2@digitalmars.com> wrote:
> On 3/27/2014 5:45 AM, "Ola Fosheim Grøstad" <ola.fosheim.grostad+dlang@gmail.com>" wrote:
>> On Thursday, 27 March 2014 at 12:35:04 UTC, Steven Schveighoffer wrote:
>>> I think we should work on making a protocol that does not require awkward
>>> calls, rather than alienating developers who don't follow the awkward protocol.
>>
>> This is it.
>
> Sure, but what is awkward about empty-front-popFront?
>
> You can still always use:
>
> foreach (e; range) { ... }
>
> which will follow the correct protocol automatically.
If this is all we needed, ranges would never have been invented.
-Steve
|
March 27, 2014 Re: protocol for using InputRanges | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 3/27/2014 2:13 PM, Steven Schveighoffer wrote: > Note that a stream makes a terrible range, simply because of what you say -- > reading is destructive, and determining emptiness is dependent on reading. You > need a buffered stream to make a good range, and then the logic becomes much > more straightforward. The range becomes the one element buffer in this case. It is completely workable. > The awkwardness for shoehorning streams into ranges I see is that the > advancement (popFront) and the check for termination (empty) are decoupled, when > in reality they are synced for a stream. This REQUIRES a sticky bit for popFront > to communicate with empty on whether it is EOF or not. The range protocol is designed to work with streams. It's a giant fail if they do not, or if you want to create a separate, non-range universe to deal with streams. > Even a single byte buffer is not enough, you need a bool to indicate the stream > is done. Right. But empty for a stream still has to read. Just follow the protocol, and the range will work, even with streams. |
March 27, 2014 Re: protocol for using InputRanges | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 3/27/2014 1:59 PM, Steven Schveighoffer wrote: > On Thu, 27 Mar 2014 16:53:35 -0400, Walter Bright <newshound2@digitalmars.com> > wrote: > >> On 3/27/2014 9:12 AM, monarch_dodra wrote: >>> If you initialized the next element in both constructor >> >> As mentioned earlier, requiring this of a range constructor makes it >> impossible to separate composition of a range with using it. > > Not impossible. Use lazy initialization. That still doesn't work, because then you could be calling front, and front might fail if there's no input. What is wrong with following the protocol? Why must we introduce all these caveats for ranges, like streams not working, front that can fail, can't do C# style LINQ, etc.? For what gain? > It only makes sense if you are using empty in your processing of the range. I.e. follow the danged protocol and it works. |
March 27, 2014 Re: protocol for using InputRanges | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Thu, 27 Mar 2014 17:24:11 -0400, Walter Bright <newshound2@digitalmars.com> wrote: > On 3/27/2014 2:13 PM, Steven Schveighoffer wrote: >> Note that a stream makes a terrible range, simply because of what you say -- >> reading is destructive, and determining emptiness is dependent on reading. You >> need a buffered stream to make a good range, and then the logic becomes much >> more straightforward. > > The range becomes the one element buffer in this case. It is completely workable. > A 1 byte buffered stream? If it's performance you are looking for, you will not find it there. > The range protocol is designed to work with streams. It's a giant fail if they do not, or if you want to create a separate, non-range universe to deal with streams. Ranges work well on top of buffered streams, but not AS streams. >> Even a single byte buffer is not enough, you need a bool to indicate the stream >> is done. > > Right. But empty for a stream still has to read. Just follow the protocol, and the range will work, even with streams. > A stream requires one primitive -- read. In one function call, you get the data you want, you can tell if it's empty, and the stream object does not need to concern itself with projecting a cached element. Adding range primitives on top of a stream does not make sense. -Steve |
March 27, 2014 Re: protocol for using InputRanges | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Thu, 27 Mar 2014 17:28:05 -0400, Walter Bright <newshound2@digitalmars.com> wrote: > On 3/27/2014 1:59 PM, Steven Schveighoffer wrote: >> On Thu, 27 Mar 2014 16:53:35 -0400, Walter Bright <newshound2@digitalmars.com> >> wrote: >> >>> On 3/27/2014 9:12 AM, monarch_dodra wrote: >>>> If you initialized the next element in both constructor >>> >>> As mentioned earlier, requiring this of a range constructor makes it >>> impossible to separate composition of a range with using it. >> >> Not impossible. Use lazy initialization. > > That still doesn't work, because then you could be calling front, and front might fail if there's no input. In the cases where you know there is input, that's not true. What I am protesting is the idea that you *know* input exists, you must still call empty. Front is enough in that case. > What is wrong with following the protocol? Why must we introduce all these caveats for ranges, like streams not working, front that can fail, can't do C# style LINQ, etc.? For what gain? There is no gain to requiring empty on ranges where you logically prove they are not empty. It's a wasted call. For things where you're not sure if they are empty or not (e.g. an input file), of course empty is required to be called, and of course it may do some processing to determine that. But I would only expect that on the first call. Subsequent checks would already be done by popFront. >> It only makes sense if you are using empty in your processing of the range. > > I.e. follow the danged protocol and it works. I mean, if you are calling empty regularly, because you aren't sure whether the elements are there. That's not always the case, sometimes you are sure the elements are there. Requiring a call to empty to do anything other than to check whether a range is empty, is just plain wrong. I'm sure there's better ways to implement what you want without stitching the functionality onto empty. -Steve |
March 27, 2014 Re: protocol for using InputRanges | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On 3/27/14, 1:58 PM, Walter Bright wrote:
> On 3/27/2014 12:50 PM, Andrei Alexandrescu wrote:
>> Yah, agreed. -- Andrei
>
> Completely unworkable. To determine if a range is empty or not, it may
> have to actually read from its input. TTYs are an example. Although
> empty may then cache the result, and not read the second time it is
> called, an observer of TTY could see that an item was read from the TTY.
That's a good point too.
Andrei
|
March 27, 2014 Re: protocol for using InputRanges | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On 3/27/14, 2:24 PM, Walter Bright wrote: > The range protocol is designed to work with streams. It's designed to work with containers. > It's a giant fail > if they do not, or if you want to create a separate, non-range universe > to deal with streams. It's not a giant fail, we just need to adjust the notion. Andrei |
March 27, 2014 Re: protocol for using InputRanges | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Thursday, 27 March 2014 at 21:54:00 UTC, Andrei Alexandrescu wrote:
> On 3/27/14, 1:58 PM, Walter Bright wrote:
>> On 3/27/2014 12:50 PM, Andrei Alexandrescu wrote:
>>> Yah, agreed. -- Andrei
>>
>> Completely unworkable. To determine if a range is empty or not, it may
>> have to actually read from its input. TTYs are an example. Although
>> empty may then cache the result, and not read the second time it is
>> called, an observer of TTY could see that an item was read from the TTY.
>
> That's a good point too.
>
> Andrei
Yes, but the "observability" should be sort lived, since empty is virtually guaranteed to be followed by "front" anyways. If both front/empty do the same (lazy) operation on the stream, then whether or not empty was called isn't really "observable" (to a certain extent).
In contrast, having front completly fail if empty was NOT called, means "empty" has a hell of a lot of observable side effect.
|
March 27, 2014 Re: protocol for using InputRanges | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | >> Even a single byte buffer is not enough, you need a bool to indicate the stream
>> is done.
>
> Right. But empty for a stream still has to read. Just follow the protocol, and the range will work, even with streams.
The protocol is not intuitive. I'm not entirely against having to call something to do lazy initialization but it's not like anyone will expect empty @property to lazily initialize.
Empty and front could be methods added by a mixin template which would use efficient methods with strict protocol implemented by the user.
|
Copyright © 1999-2021 by the D Language Foundation