foreach with a default range

Steven Schveighoffer via Digitalmars-d digitalmars-d at puremagic.com
Thu Jun 11 13:54:45 PDT 2015


On 6/11/15 4:31 PM, Jonathan M Davis wrote:
> On Thursday, 11 June 2015 at 13:09:21 UTC, Steven Schveighoffer wrote:
>> On 6/11/15 8:54 AM, Dmitry Olshansky wrote:
>>> On 11-Jun-2015 15:22, Steven Schveighoffer wrote:
>>>> On 6/11/15 4:24 AM, Dmitry Olshansky wrote:
>>>>
>>>>> Already works. Just define opSlice for container that returns a range
>>>>> and then:
>>>>>
>>>>> foreach(elem; container) {}
>>>>>
>>>>> is lowered to:
>>>>>
>>>>> foreach(elem; container[]) {}
>>>>>
>>>>
>>>> I think you want to do opIndex which takes no parameters.
>>>
>>> Ehm. How is being more logical or what is the reason?
>>>
>>>> opSlice is no
>>>> longer supposed to be used that way (though it still works for
>>>> backwards
>>>> compatibility).
>>>
>>> Now that's the real news. Me thinks slice it on foreach was added
>>> speicfically for std.container back in 2012. Where the docs for the
>>> later change (well, both of them for that matter)?
>>>
>>
>> See this thread, was news to me too:
>> http://forum.dlang.org/thread/luadir$t0g$1@digitalmars.com#post-mailman.669.1410325102.5783.digitalmars-d-learn:40puremagic.com
>>
>>
>> The rationale was in order to support multi-dimensional slicing.
>
> Yes, but isn't it specifically for the case where you're using
> multi-dimensional arrays and _not_ the general case? Certainly, that's
> what I understood when talking with John Colvin about how the
> multi-dimensional array support works. It sounded like the compiler
> started looking for other stuff to be implemented if you defined opIndex
> with no parameters, whereas it doesn't if opSlice with no parameters is
> defined. So, I wouldn't start using opIndex that way without really
> understanding what's going on there in detail.

At this point, I think opIndex() and opSlice() are identical (and the 
compiler I think will try opIndex() first), but I don't know what 
happens if you have other methods defined.

> Regardless, from an idiomatic perspective, it makes far more sense to be
> implementing opSlice with empty parameters than opIndex simply based on
> what the operators are for. So, if you can do both, I'd argue that you
> should be using opSlice with no parameters if you don't need whatever
> the heck is going on with multi-dimensional arrays.

No, opIndex with no parameters is more idiomatic. The other way is just 
supported for legacy reasons.

It's pretty simple to understand. Let's start from a 3-arg slicing 
operation:

o[a..b, c, d..e] => o.opIndex(o.opSlice!0(a, b), c, o.opSlice!2(d, e));

Now, let's remove parameters:

o[a..b, c] => o.opIndex(o.opSlice!0(a, b), c);
o[a..b] => o.opIndex(o.opSlice!0(a, b));
o[] => o.opIndex();

It makes sense, and is very extendable, and uniform. You can deal with 
this much easier when imlplementing some sort of wrapping than one that 
has to do something different depending on how many args are passed 
inside the []. I like the new way.

-Steve


More information about the Digitalmars-d mailing list