RFC on range design for D2

Fawzi Mohamed fmohamed at mac.com
Fri Sep 12 09:10:28 PDT 2008


On 2008-09-12 17:48:02 +0200, Andrei Alexandrescu 
<SeeWebsiteForEmail at erdani.org> said:

> Fawzi Mohamed wrote:
>> I like the new proposal much more than the first.
>> 
>> I believe you will be able to use it successfully in std.algorithm.
>> I still would have preferred an operation like a sameHead or 
>> compareHeadPosition (that might or might not return the order, but at 
>> least tests for equality) so that upon request (-debug flag?) one would 
>> be able to make all range operation safe (with overhead) in a generic 
>> way, but it is up to you.
> 
> Comparing for equality of heads is very important. For now you can 
> obtain it as a non-primitive by invoking:
> 
> auto sameHead = r.before(s).done;

nice I hadn't thought about this

> The above also show how "done" is not always very expressive. Also you 
> can compare whether two ranges have the same end by invoking:
> 
> auto sameRange = r is s;

I suppose that you mean that "is" compares both the start and the end...

>> I what I really care about is the following:
>> I want foreach magic on all objects that support .done and .next, even 
>> if they are not ranges.
>> foreach is about iteration, iteration needs only .done and .next (a 
>> generator, iterator whatever), and it should work with that.
>> Do not force the range idea on foreach iteration.
>> foreach is a language construct, not a library one and should allow for 
>> maximum flexibility.
> 
> Yes. Walter asked me to send him the syntactic transformation that 
> foreach and foreach_reverse need to do. Duck typing will be used so as 
> long as you define the proper names you're in good shape.

very nice, this is important because generic algorithms aside you might 
want to loop on all sort of things.

>> As extra nicety as each generator/iterator/range returns just one 
>> object I would like to be able to do:
>> 
>> // i counts starting from 1, j iterates on iterJ and in parallel k 
>> iterates on a.all
>> foreach(i,j,k;1..$,iterJ,a.all){
>>     //...
>> }
>> 
>> and have it expanded to
>> 
>> Range!(int) r1=1..$;
>> alias iterJ r2;
>> typeof(a.all) r3=a.all;
>> while(!(r1.done || r2.done || r3.done)){
>>     typeof(r1.next) i=r1.next;
>>     typeof(r2.next) j=r2.next;
>>     typeof(r3.next) k=r3.next;
>>     //...
>> }
> 
> Walter and I were discussing about ranges exposing key, key1, ... keyn. 
> In that case foreach with multiple arguments would work, and would bind 
> each of the extra argument to key, key1 etc. respectively.

I like the possibility to give several iterators at once to foreach, so 
that you never have to define two opApply (one with index, one 
without), but you can easily add a counter if you want to.

You can solve this also by have a "combiner" of iterators, but in my 
opinion it is uglier.

If you allow an iterator to return several objects and also to have 
several iterators that are advanced together should use another syntax 
than the one I proposed, something like

foreach(i;1..$; j; iterJ; k,l; multiIter){

}

otherwise matching iteration variables with iterators gets a mess.

Fawzi



More information about the Digitalmars-d-announce mailing list