March 27, 2014

On 27.03.2014 09:42, Walter Bright wrote:
> On 3/26/2014 11:53 PM, Rainer Schuetze wrote:
>> IIUC what you are proposing would be covered better by removing front
>> and return
>> the value by popFront.
>
> Different things being ranged over make different decisions as to what
> goes into each function.
>
>> Instead of forcing strong, breaking and sometimes unintuitive semantics
>
> I don't understand what is so unintuitive about:
>
>      while (!empty) { ... front ...; popFront(); }

This loop is intuitive. Not being allowed to call empty or front multiple times or not at all is unintuitive. They should not be named as if they are properties then.

>
> What I do find unintuitive and unattractive is all those flags in the
> range implementation.
>
>> we could also improve dmd's optimizer.
>
> Yes, that's true. The thing about optimizers, though, is they work on
> patterns. If your code doesn't quite match the right pattern, it won't
> tickle the optimization you might be expecting. The pattern for
> recognizing the ROL and ROR patterns is one such.

I guess gcc doesn't use patterns here, but value propagation and notices that all the checks are unnecessary.
March 27, 2014

On 27.03.2014 10:06, Walter Bright wrote:
> On 3/26/2014 11:53 PM, Rainer Schuetze wrote:
>>  This caching range example:
>>
>> ///////////////////////////////////
>> T getc(T)();
>>
>> struct irange(T)
>> {
>>    bool _cached;
>>    T _cache;
>>
>>    this(T[] arr) { _cached = false; }
>>    bool empty() {
>>      if(_cached) return false;
>>      _cache = getc!T();
>>      return (_cache < 0);
>
> What happens if empty is called twice in a row? Two characters get read!
> That isn't right.

Good catch. Somehow I pasted the wrong version, but posted the corrections a few minutes later.

>
>>    }
>>    T front() { empty(); return _cache; }
>
> What happens if empty returns true? EOF? I don't think that's intuitive.
> You could have front throw, but that prevents anyone from building
> nothrow ranges.

The caller is told to guarantee that empty must not return true. I just didn't wanted to repeat the stuff in empty. GDC removed it anyway...
March 27, 2014
On 3/27/14, 11:53 AM, Steven Schveighoffer wrote:
> On Thu, 27 Mar 2014 12:02:16 -0400, monarch_dodra
> <monarchdodra@gmail.com> wrote:
>
>> On Thursday, 27 March 2014 at 15:19:37 UTC, Andrei Alexandrescu wrote:
>>> On 3/27/14, 3:49 AM, "Marc Schütz" <schuetzm@gmx.net>" wrote:
>>>> I was originally going to do that, but then I took a closer look at the
>>>> documentation, which says ([1] in the documentation of
>>>> `isInputRange()`):
>>>>
>>>> "Calling r.front is allowed only if calling r.empty has, or would have,
>>>> returned false."
>>>
>>> Probably we need to amend that. For efficient ranges, front() and
>>> popFront() should only be guaranteed to work if either empty() or
>>> length() were evaluated first, and they returned false or nonzero,
>>> respectively.
>>
>> I just want to point out that I think allowing empty to have an
>> *observable* side effect will have cataclysmic repercussion in
>> validating a release build, what with all our "assert(!empty);" calls
>> and all.
>
> This is an excellent point. assert(!empty) is everywhere.
>
> -Steve

Yah, agreed. -- Andrei
March 27, 2014
On 3/27/2014 12:24 PM, Rainer Schuetze wrote:
> The caller is told to guarantee that empty must not return true.

I think that is the very definition of looking under the hood in order to violate protocol. A range CANNOT be written generically and support that.
March 27, 2014
On 3/27/2014 12:21 PM, Rainer Schuetze wrote:
> This loop is intuitive. Not being allowed to call empty or front multiple times
> or not at all is unintuitive. They should not be named as if they are properties
> then.

I can concede that. But I can't concede being able to call front without first calling empty, or calling popFront without calling empty and front, or requiring 'pump priming' in the constructor.
March 27, 2014
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.

As also mentioned earlier, this throws under the bus entire categories of use cases for ranges, all to avoid a single call to 'empty'.

March 27, 2014
On 3/27/2014 3:49 AM, "Marc Schütz" <schuetzm@gmx.net>" wrote:
> I was originally going to do that, but then I took a closer look at the
> documentation, which says ([1] in the documentation of `isInputRange()`):
>
> "Calling r.front is allowed only if calling r.empty has, or would have, returned
> false."
>
> (And the same for `popFront()`.)
>
> That is, the documentation more or less explicitly states that you don't
> actually need to call `empty` if you know it returned `true`.
>
> [1] http://dlang.org/phobos/std_range.html

Right, it does say that, and it is seriously wrong.
March 27, 2014
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.
March 27, 2014
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.

> As also mentioned earlier, this throws under the bus entire categories of use cases for ranges, all to avoid a single call to 'empty'.

This is going to look weird:

r.empty;

// now we can use it...

It only makes sense if you are using empty in your processing of the range.

-Steve
March 27, 2014
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.