www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - foreach and retro

reply Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
Hello all,

A problem with the retro function from std.range -- although it apparently 
operates on a bidirectional range, it fails when used with foreach requesting 
both value and index.  Running this code:

////////////////////////////////////////////////
import std.range, std.stdio;

void main()
{
       double[] a = [ 0, 1, 2, 3, 4, 5 ];

       foreach(i, x; retro(a))
             writeln(i, "\t", x);
}
////////////////////////////////////////////////

... results in an error: "cannot infer argument types".

Is there any reason why this should be so, or is it (as it seems to me) just a
bug?

Thanks & best wishes,

     -- Joe
Jul 02 2012
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07/02/2012 05:36 PM, Joseph Rushton Wakeling wrote:
 Hello all,

 A problem with the retro function from std.range -- although it
 apparently operates on a bidirectional range, it fails when used with
 foreach requesting both value and index.  Running this code:

 ////////////////////////////////////////////////
 import std.range, std.stdio;

 void main()
 {
        double[] a = [ 0, 1, 2, 3, 4, 5 ];

        foreach(i, x; retro(a))
              writeln(i, "\t", x);
 }
 ////////////////////////////////////////////////

 ... results in an error: "cannot infer argument types".

 Is there any reason why this should be so, or is it (as it seems to me)
 just a bug?

 Thanks & best wishes,

      -- Joe

What would be your expected output?
Jul 02 2012
prev sibling next sibling parent "Tobias Pankrath" <tobias pankrath.net> writes:
 What would be your expected output?

From the inner to the outer expression: First the range is reversed and then the elements of this range are enumerated.
Jul 02 2012
prev sibling next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Joseph Rushton Wakeling:

       double[] a = [ 0, 1, 2, 3, 4, 5 ];

       foreach(i, x; retro(a))
             writeln(i, "\t", x);

It's not a bug, it's caused by how ranges like retro work. retro yields a single item. In D you can't overload on return values, so foreach can't try to call a second retro.front overload that yields an (index,item) tuple (that later foreach is able to unpack on the fly) instead of the retro.front that just yields the item. To solve that problem this is what I have suggested to add to Phobos: http://d.puremagic.com/issues/show_bug.cgi?id=5550 Bye, bearophile
Jul 02 2012
parent travert phare.normalesup.org (Christophe Travert) writes:
"bearophile" , dans le message (digitalmars.D:171013), a écrit :
 It's not a bug, it's caused by how ranges like retro work. retro 
 yields a single item. In D you can't overload on return values, 

But you can overload OpApply. -- Christophe
Jul 02 2012
prev sibling next sibling parent Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 02/07/12 17:48, Timon Gehr wrote:
 What would be your expected output?

I'd expect to see 0 5 1 4 2 3 3 2 4 1 5 0 i.e. as if I was foreach-ing over an array with the same values in inverted order.
Jul 02 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
On Monday, 2 July 2012 at 16:49:06 UTC, Joseph Rushton Wakeling 
wrote:
 On 02/07/12 17:48, Timon Gehr wrote:
 What would be your expected output?

I'd expect to see 0 5 1 4 2 3 3 2 4 1 5 0 i.e. as if I was foreach-ing over an array with the same values in inverted order.

Use the .array() property: auto Range(alias func, Args...)(Args args) { return func(args).array(); } void main() {} double[] ad = [ 0, 1, 2, 3, 4, 5 ]; foreach(index, x; Range!(retro)(ad)) { writeln(index, "\t", x); } }
Jul 02 2012
prev sibling next sibling parent kenji hara <k.hara.pg gmail.com> writes:
D does not provide index for the range iteration.
Instead, you can create 'zipped' range.

void main() {
      auto intr = sequence!"n"();  // 0, 1, 2, ...
      double[] a = [ 0, 1, 2, 3, 4, 5 ];
      foreach(i, x; zip(intr, retro(a)))
            writeln(i, "\t", x);
}

zip(intr, retro(a)) is a range of Tuple!(size_t, double), and foreach
automatically expand the tow fields of zip front into i and x like
follows.

      foreach(__e; zip(intr, retro(a))) {
            auto i = __elem[0], x = __elem[1];   // inserted by the compiler
            writeln(i, "\t", x);
      }

After all, you can get 'index' for range iteration.

Kenji Hara

2012/7/3 Joseph Rushton Wakeling <joseph.wakeling webdrake.net>:
 On 02/07/12 17:48, Timon Gehr wrote:
 What would be your expected output?

I'd expect to see 0 5 1 4 2 3 3 2 4 1 5 0 i.e. as if I was foreach-ing over an array with the same values in inverted order.

Jul 02 2012
prev sibling next sibling parent Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 02/07/12 18:43, bearophile wrote:
 It's not a bug, it's caused by how ranges like retro work. retro yields a
single
 item. In D you can't overload on return values, so foreach can't try to call a
 second retro.front overload that yields an (index,item) tuple (that later
 foreach is able to unpack on the fly) instead of the retro.front that just
 yields the item.

Ahh, OK. Clear, just a little surprising.
 To solve that problem this is what I have suggested to add to Phobos:
 http://d.puremagic.com/issues/show_bug.cgi?id=5550

Looks like a nice idea! The reason I was interested was because of a case where a foreach_reverse was called for across an array, but where it was useful to flip the indices as well.
Jul 04 2012
prev sibling parent Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 02/07/12 18:57, kenji hara wrote:
 D does not provide index for the range iteration.
 Instead, you can create 'zipped' range.

Oh, cool. That's a nice feature that I can think of other uses for ... :-)
Jul 04 2012