www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Ranges and backward iteration

reply "Andrew" <andrew.spott gmail.com> writes:
I have a use case where I would like to be able to pass both a
forward and backward iteration of an array to a function:

void foo(InputR, OutputR)(InputR i, OutputR j)
    if (isInputRange!InputR && isOutputRange!(OutputR, InputR))
{
...
}

main()
{
     //forward:
     foo(a[1..n], b[1..n]);
     //backward:
     foo(retro(a[n..$]), retro(b[n..$]));

     //do stuff with b as it has been constructed now...
}

This doesn't work (retro doesn't appear to return a Range, but
rather an object of type "Result", which I don't understand), but
the intent should be clear.

How do I do this? What am I missing?  There doesn't seem to be a
"backward iterator" equivalent in std.range.
Jul 29 2012
next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Sunday, 29 July 2012 at 23:26:09 UTC, Andrew wrote:
 I have a use case where I would like to be able to pass both a
 forward and backward iteration of an array to a function:

 void foo(InputR, OutputR)(InputR i, OutputR j)
    if (isInputRange!InputR && isOutputRange!(OutputR, InputR))
 {
 ...
 }

 main()
 {
     //forward:
     foo(a[1..n], b[1..n]);
     //backward:
     foo(retro(a[n..$]), retro(b[n..$]));

     //do stuff with b as it has been constructed now...
 }

 This doesn't work (retro doesn't appear to return a Range, but
 rather an object of type "Result", which I don't understand), 
 but
 the intent should be clear.

 How do I do this? What am I missing?  There doesn't seem to be a
 "backward iterator" equivalent in std.range.
isBidirectionalRange perhaps? [quote] Returns true if R is a bidirectional range. A bidirectional range is a forward range that also offers the primitives back and popBack. The following code should compile for any bidirectional range. [/quote]
Jul 29 2012
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 07/30/2012 01:26 AM, Andrew wrote:
 I have a use case where I would like to be able to pass both a
 forward and backward iteration of an array to a function:

 void foo(InputR, OutputR)(InputR i, OutputR j)
 if (isInputRange!InputR && isOutputRange!(OutputR, InputR))
 {
 ...
 }

 main()
 {
 //forward:
 foo(a[1..n], b[1..n]);
 //backward:
 foo(retro(a[n..$]), retro(b[n..$]));

 //do stuff with b as it has been constructed now...
 }

 This doesn't work
Works for me. This is how I test: void foo(InputR, OutputR)(InputR i, OutputR j) if (isInputRange!InputR && isOutputRange!(OutputR, InputR)){ j.put(i); } void main() { int[] a=[2,0,0,3], b=[1,2,3,4]; int n=2; foo(a[0..n], b[0..n]); assert(b==[2,0,3,4]); foo(retro(a[n..$]), retro(b[n..$])); assert(b==[2,0,0,3]); }
 (retro doesn't appear to return a Range, but
 rather an object of type "Result", which I don't understand)
'Result' implements the range interface and is a local struct of the 'retro' function.
, but the intent should be clear.

 How do I do this? What am I missing? There doesn't seem to be a
 "backward iterator" equivalent in std.range.
retro should do the job.
Jul 29 2012
parent "Andrew" <andrew.spott gmail.com> writes:
On Sunday, 29 July 2012 at 23:42:09 UTC, Timon Gehr wrote:
 On 07/30/2012 01:26 AM, Andrew wrote:
 I have a use case where I would like to be able to pass both a
 forward and backward iteration of an array to a function:

 void foo(InputR, OutputR)(InputR i, OutputR j)
 if (isInputRange!InputR && isOutputRange!(OutputR, InputR))
 {
 ...
 }

 main()
 {
 //forward:
 foo(a[1..n], b[1..n]);
 //backward:
 foo(retro(a[n..$]), retro(b[n..$]));

 //do stuff with b as it has been constructed now...
 }

 This doesn't work
Works for me. This is how I test: void foo(InputR, OutputR)(InputR i, OutputR j) if (isInputRange!InputR && isOutputRange!(OutputR, InputR)){ j.put(i); } void main() { int[] a=[2,0,0,3], b=[1,2,3,4]; int n=2; foo(a[0..n], b[0..n]); assert(b==[2,0,3,4]); foo(retro(a[n..$]), retro(b[n..$])); assert(b==[2,0,0,3]); }
 (retro doesn't appear to return a Range, but
 rather an object of type "Result", which I don't understand)
'Result' implements the range interface and is a local struct of the 'retro' function.
, but the intent should be clear.

 How do I do this? What am I missing? There doesn't seem to be a
 "backward iterator" equivalent in std.range.
retro should do the job.
Awesome, thanks... In my code, I had a "ref" for the second argument, which apparently made the type signature not work.
Jul 29 2012