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