July 09, 2012
On Tuesday, 13 July 2010 at 03:48:08 UTC, Andrei Alexandrescu wrote:
> I think I figured out a comfortable and all-encompassing means to define a simplified interface for an input range.
>
> Currently input ranges need to define empty, front, and popFront. That works but it's a bit heavy for simple input ranges. We've been discussing simplified interfaces in this group but couldn't find one that satisfied all use cases.

This feels quite similar to "consumeFront"? As a matter of fact, isn't it just exchanging:

"Check Not Empty" then "consumeFront"
for
"getNext" then "checkNotNull"

>Semantics: if the range wants to expose addresses of its elements, it returns a pointer to the current element and also advances to the next element. Otherwise (i.e. the range does not have or does not want to expose addresses of its elements), the range fills "item" with the current value, again moves on to the next value, and returns &item.

My big worry here is that when the range does _not_ want to provide a pointer to its internals, the caller has no way of knowing it. Modifying the pointed object may or may not modify the range.

For example, "std.algorithm.map" on an Array!bool simply can't work with getNext. Since the implementer has no idea what he is operating on, the conclusion is that he simply can't use getNext when mutation is possible.

July 09, 2012
On Tuesday, 13 July 2010 at 12:39:19 UTC, Steven Schveighoffer wrote:
> On Mon, 12 Jul 2010 23:48:05 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>> We've been discussing simplified interfaces in this group but couldn't find one that satisfied all use cases.
>>
>> Consider this:
>>
>> T* getNext(R, T)(ref R range, ref T item);
>>
>> Semantics: <snip>
>
> Yes, yes, yes!
>
> -Steve

Oh dear. I can see this is getting ugly, pretty darn fast...

If you need to /pass/ TWO parameters by _reference_ AND return a pointer to a /templated/ method _just_ to get 1 element out of a range/array, the design is horribly wrong.

Imagine all the sorts of problems newcomers would have with learning this.

Not to mention the troubles /everyone/ would have with having this templated method a class. (How do you override it?)

Really, doing something simple should be simple.

I don't have any brilliant ideas, but one guess would be nullable types... if you can return a nullable value, your interface for an interface could just be:

	T?  next();

and that's it... it would return null if nothing is left. (The compiler can just set the null flag and ignore initializing the rest of the struct if the result is null.)


Anyway, whatever we do... _please_ don't make it something like that suggestion above >_< thanks
July 09, 2012
On Monday, 9 July 2012 at 08:55:21 UTC, monarch_dodra wrote:
> For example, "std.algorithm.map" on an Array!bool simply can't work with getNext. Since the implementer has no idea what he is operating on, the conclusion is that he simply can't use getNext when mutation is possible.

Re-reading the documentation of "map", I realize this is a bad example, but you get the point. "initializeAll" would be a better example (I think).
July 09, 2012
On 7/9/12 5:14 AM, Mehrdad wrote:
> Really, doing something simple should be simple.
>
> I don't have any brilliant ideas, but one guess would be nullable
> types... if you can return a nullable value, your interface for an
> interface could just be:
>
> T? next();
>
> and that's it... it would return null if nothing is left.

What if you want to return a reference so the user can change it?

Andrei

July 09, 2012
On Monday, 9 July 2012 at 14:03:17 UTC, Andrei Alexandrescu wrote:
> On 7/9/12 5:14 AM, Mehrdad wrote:
>> Really, doing something simple should be simple.
>>
>> I don't have any brilliant ideas, but one guess would be nullable
>> types... if you can return a nullable value, your interface for an
>> interface could just be:
>>
>> T? next();
>>
>> and that's it... it would return null if nothing is left.
>
> What if you want to return a reference so the user can change it?
>
> Andrei

Huh? You don't... it's an input iterator, not an output iterator!
What would you be changing, exactly?

D's return-by-reference doesn't work the way you expect anyway, so it's kinda pointless worrying about it....

@property ref int foo() { }
@property void foo(int v) { }
foo = 2;  // huh?
July 09, 2012
On Monday, 9 July 2012 at 14:07:26 UTC, Mehrdad wrote:
> Huh? You don't... it's an input iterator, not an output iterator!

er... s/iterator/range/g
July 09, 2012
On Monday, 9 July 2012 at 14:07:26 UTC, Mehrdad wrote:
> Huh? You don't... it's an input iterator, not an output iterator!
> What would you be changing, exactly?
>

Not to mention, what's the use case for it?
July 09, 2012
On 7/9/12 10:07 AM, Mehrdad wrote:
> On Monday, 9 July 2012 at 14:03:17 UTC, Andrei Alexandrescu wrote:
>> On 7/9/12 5:14 AM, Mehrdad wrote:
>>> Really, doing something simple should be simple.
>>>
>>> I don't have any brilliant ideas, but one guess would be nullable
>>> types... if you can return a nullable value, your interface for an
>>> interface could just be:
>>>
>>> T? next();
>>>
>>> and that's it... it would return null if nothing is left.
>>
>> What if you want to return a reference so the user can change it?
>>
>> Andrei
>
> Huh? You don't... it's an input iterator, not an output iterator!

The idea of an input range is that it works seamlessly with the more capable ranges.

Andrei
July 09, 2012
On Monday, 9 July 2012 at 14:21:33 UTC, Andrei Alexandrescu wrote:
>> Huh? You don't... it's an input iterator, not an output iterator!
>
> The idea of an input range is that it works seamlessly with the more capable ranges.
>
> Andrei

You mean 'foreach'? That should be using opApply if it wants to take outputs by ref, not input range capabilities.

Or is there some other constructor you're referring to? Because I don't see any overlap in the constructs between input and output ranges.
July 09, 2012
On 7/9/12 10:31 AM, Mehrdad wrote:
> On Monday, 9 July 2012 at 14:21:33 UTC, Andrei Alexandrescu wrote:
>>> Huh? You don't... it's an input iterator, not an output iterator!
>>
>> The idea of an input range is that it works seamlessly with the more
>> capable ranges.
>>
>> Andrei
>
> You mean 'foreach'? That should be using opApply if it wants to take
> outputs by ref, not input range capabilities.
>
> Or is there some other constructor you're referring to? Because I don't
> see any overlap in the constructs between input and output ranges.

I think it's about the notion of "input range" that is confusing, a better name would be "single-pass range". One should be perfectly capable of assigning to elements of an input range. A built-in slice is an input range.

Andrei