Iterators for D

Walter Bright newshound at digitalmars.com
Mon Nov 6 18:26:35 PST 2006


Kirk McDonald wrote:
> Walter Bright wrote:
>> You've always been able to:
>>     int* p;
>>     p[1] = ...
> Wouldn't that be p[0] = ...?

I must have misunderstood you. I thought you were asking if [n] worked 
on pointers. Yes, it does.

> Is that how you intend to use opIndex to "dereference" the iterator? 
> That's /terrifying/. Although it is consistent with pointers, using [0] 
> for everything is just asking for trouble with regards to 
> non-random-access iterators. And though it's probably not totally 
> meaningless to a random reader of the code, it comes pretty darned close.

I agree it might be startling at first because it's unusual. Once one is 
past that, however, is it that bad?

>>> If a class provides .begin, .end, and opApply, one of the two 
>>> iteration methods has to take precedence. I would hope it's opApply.
>>
>> I was leaning towards the other way around.
>>
> 
> It is slightly easier and clearer to explicitly say:
> 
> foreach(e; t.begin) { }
> 
> than
> 
> foreach(e; &t.opApply) { }
> 
> opApply is an operator overload. .begin would just be a special method. 
> I would expect the operator to take precedence.

The:
	foreach(e; t.begin) { }
would not be supported. It would be:
	foreach (e; t) { }
If an aggregate had both, and iterators would be chosen by default, 
overriding with:
	foreach (e; &t.opApply) { }
would not require any new conventions or syntax. So I think this is the 
right way to go.


>>> For a type T, its associated iterator type should be available via 
>>> T.iterator. This has to be standard.
>>
>> It's not needed, as typeof(T.begin) will do it.
>>
> 
> Due to the way in which D's type inference from properties works, you'll 
> need typeof(T.begin()). Otherwise, it will derive the type of the method 
> itself. (Which isn't even a valid type, as such.)

Yes, you're right.

>> No. opIndex()
> 
> I'm referring specifically to the no-index form of opSlice (meaning i[] 
> would "dereference" the iterator). (A no-index opIndex doesn't work.) 
> This of course is inconsistent with pointers, so saying i[0] is better 
> on that count.

Ok, I understand now where you were coming from with the slice.


>>> I opPostInc()
>>
>> Probably opAddAssign()
> 
> Oh, there's another one:
> 
> int opEquals(I)

Yes, I'd overlooked that.

>> I could go either way with that.
> Neither one is particularly elegant.

True, but that inelegance is hidden away in the library, but the 
flexibility is probably worth it.

>> I think it does provide enough, in fact, it will be less wacky than in 
>> C++ (look at the wretched iterator/const_iterator dichotomy). It'll 
>> work with core arrays, and will not need those typedefs.
> Without the ability to overload the dereference operator, any attempt to 
> write a class that behaves like a pointer in D will be unwieldy, or at 
> least ugly. Admittedly, this isn't much of an issue when just using 
> foreach, but might be an issue with any kind of STL-like algorithms 
> library. (Which is what you're inviting when using C++'s iterator 
> semantics.)

I still think it isn't necessary, but you might be thinking of a use 
case I haven't. Can you provide an example?



More information about the Digitalmars-d mailing list