Super-dee-duper D features

Andrei Alexandrescu (See Website For Email) SeeWebsiteForEmail at erdani.org
Tue Feb 13 20:51:00 PST 2007


kris wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>> kris wrote:
>>
>>> Andrei Alexandrescu (See Website For Email) wrote:
>>>
>>>> Bill Baxter wrote:
>>>>
>>>>> kris wrote:
>>>>>
>>>>>> kris wrote:
>>>>>>
>>>>>>> Bill Baxter wrote:
>>>>>>>
>>>>>>>> Frits van Bommel wrote:
>>>>>>>>
>>>>>>>>> By the way, would the new loop syntax allow more than two 
>>>>>>>>> collections to be simultaneously iterated?
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> Whoa!  I certainly hope so.  It hadn't even occurred to me that 
>>>>>>>> Andrei might mean this syntax can only be used for just two 
>>>>>>>> collections.  If that's the case then ... ick.
>>>>>>>>
>>>>>>>> --bb
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> InterleavedIterator does multiple collections via using multiple 
>>>>>>> instances of InterleavedIterator. It's simple to use, and only 
>>>>>>> needs to be written once. Would be better to implement some basic 
>>>>>>> iterator needs than to introduce some tricky new syntax?
>>>>>>>
>>>>>>> - Kris
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> Should have given an example. Simple case with 2 entities:
>>>>>>
>>>>>> auto two = InterleavedInterator (x, y);
>>>>>> foreach (x; two) ...
>>>>>>
>>>>>> more than 2:
>>>>>>
>>>>>> auto three = InterleavedInterator (two, z);
>>>>>> foreach (x; three) ...
>>>>>
>>>>>
>>>>>
>>>>> Should have also mentioned where one can find this mythical 
>>>>> InterleavedIterator.
>>>>
>>>>
>>>>
>>>> The issue with such a multi-iterator is that it makes it easier to 
>>>> make errors, and harder to write efficient and correct code that's 
>>>> statically verifiable.
>>>>
>>>> I'm not sure when the interleaved iterator stops iterating, but 
>>>> there are two possibilities, none of which is satisfactory:
>>>>
>>>> 1. Stop after the shortest of the two collections is done. Then user 
>>>> code must query the state of the iterator after the loop to figure 
>>>> what extra work is to be done:
>>>>
>>>> auto two = InterleavedInterator (x, y);
>>>> foreach (x; two) { ... }
>>>> if (two.MoreData(0)) {
>>>>   auto back2one = two.Project(0); // fetch the first iterator
>>>>   foreach (x ; back2one) { ... }
>>>> } else if (two.moreData(1)) {
>>>>   ... same (or)deal ...
>>>> }
>>>>
>>>> This is way more work than there should.
>>>>
>>>> 2. Stop after the longest of the two collections is done. Then user 
>>>> code must ensure _at each step_ that both iterators have meaningful 
>>>> data:
>>>>
>>>> auto two = InterleavedInterator (x, y);
>>>> foreach (x; two) {
>>>>   if (two.HasData(0)) { ... }
>>>>   else { ... only the second iter has data ... }
>>>> }
>>>>
>>>> This is unclear, verbose, and probably suboptimal.
>>>>
>>>> The scoping of foreach links the scope of the variables with their 
>>>> validity range, which rules out a class of possible errors entirely:
>>>>
>>>> foreach (x ; c1) (y ; c2) (z ; c3) {
>>>>   ... x, y, z syntactically accessible _and_ valid ...
>>>> }
>>>> continue foreach (x, z) {
>>>>   ... x is both invalid _and_ syntactically inaccessible ...
>>>> }
>>>>
>>>> As I mentioned in a different post, the fact that there are 
>>>> combinatorial potential sub-foreach statements is a non-issue.
>>>>
>>>>
>>>> Andrei
>>>
>>>
>>> If x, y, & z are of differing type, then I'd agree.
>>
>>
>> If they are of the same type and in an arbitrarily large numbers (x1, 
>> x2, x3...), we start talking about cutting through some sort of a 
>> matrix or manifold, which is an entirely different business.
> 
> So if we did have a language-based iterator (which was a hot topic 
> recently), it might take the form of a generator?

They all have their place in the language/stdlib ecosystem.

a) foreach does great when the iteration policy *and* range are both
fixed. I see this limitation as a big advantage. At least one study has
shown that most bugs occur in loops, and it's kind of annoying that C
turned the clock of progress back when it just provided the most general
and the least safe way of iteration to replace all others. Ever since
then, industrial languages followed suit, and as often happens, people
have done it that way for so long, that it took a few geniuses to figure 
out what makes sense to people on the street. So only since recently 
limited iteration started again to receive proper support.

b) iterators and generators have both the ability of stopping and 
resuming iteration. Generators are more natural when there's no real 
container (do you "iterate" random numbers? does it make sense to 
compare the input iterator to the "end of input" special iterator?) but 
have the disadvantage of fixing the iteration policy. Iterators are more 
flexible in that they offer the user the ability to devise their own 
iteration policies within a well-defined framework.

So there's a place for everyone.


Andrei




More information about the Digitalmars-d mailing list