DMD 0.170 release

Bill Baxter wbaxter at gmail.com
Tue Oct 17 08:46:50 PDT 2006


Is there any reason for not allowing a function to be used too?
Then you could also use a closure as the thing that does the iteration:

int function(int delegate(inout ElemT)) 
reversed(AggregateT,ElemT)(AggregateT array)
{
     int _innerFunc(int delegate(inout ElemT) loopBody)
     {
         int done = 0;
         for (int i = array.length-1; i >=0; i--)
         {
             done = loopBody(array[i]);
             if (done)
                 break;
         }
         return done;
     }
     return &_innerFunc;
}
...
foreach(real r; reversed!(real[],real)(areal))
{...}

--bb


Bill Baxter wrote:
> 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