DMD 0.170 release

Bill Baxter wbaxter at gmail.com
Tue Oct 17 08:00:58 PDT 2006


Bruno Medeiros wrote:
> Walter Bright wrote:
> 
>> Added foreach_reverse, which addresses a serious shortcoming.
>>
>> http://www.digitalmars.com/d/changelog.html
> 
> 
> foreach_reverse addresses a serious shortcoming? What is that, if 
> instead of:
>   foreach_reverse(Foo f; aggregate) { ...
> I can do:
>   foreach(Foo f; &aggregate.opApplyReverse) { ...
> 
> The latter form is both more general (allows any kind of iterators) and 
> more simple/orthogonal (no extra special statements are needed).

I agree.  Allowing any delegate to be used is a good move I think.  But 
the incremental value added by 'foreach_reverse' and 'opApplyReverse' 
are minimal once you can already use any delegate as the aggregate.

It would be nice to be able to write a function like "reversed" and then 
just do
     foreach(Foo f; reversed(aggregate)) { ...

To me that seems like a more clean and natural way to support a variety 
of iteration strategies without adding special-cased reverse iterators 
to the language.

Here's a somewhat limited version of that idea:
It's limited by my lack of template-fu, so it just works for arrays, and 
you have to explicitly pass too many template parameters:

class _rev_proxy(AggregateT, ElemT)
{
     this(AggregateT theObj) {
         obj = theObj;
     }
     int opApply(int delegate(inout ElemT) dg)
     {
         int done = 0;
         for (int i = obj.length-1; i >=0; i--)
         {
             done = dg(obj[i]);
             if (done)
                 break;
         }
         return done;
     }
   private:
     AggregateT obj;
}

_rev_proxy!(AggregateT,ElemT) reversed(AggregateT,ElemT)(AggregateT array)
{
     return new _rev_proxy!(AggregateT,ElemT)(array);
}

unittest
{
     void testrev() {
         int[] aint = [1,2,3,4,5,6,7];
         real[] areal = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0];

         foreach(int i; reversed!(int[],int)(aint))
         {
             printf("%d\n",i);
         }

         foreach(real r; reversed!(real[],real)(areal))
             //foreach(real r; areal)
         {
             printf("%f\n",cast(float)(r));
         }
     }
     testrev();
}


I would guess this could probably be expanded with more template-fu so 
that any class which supports a particular protocol (e.g. has a .length 
and [] operator, or a reversed() method) can automatically be reversed. 
  And then as a last resort you could always write your own 
specialization of reversed!() particularly for your class.

--bb



More information about the Digitalmars-d-announce mailing list