www.digitalmars.com         C & C++   DMDScript  

D - foreach, slices, and reverse ranges

reply Sean Kelly <sean ffwd.cx> writes:
First a quick example:

char[] a = "abc";
int x = 0, y = 1;
foreach( char c; a[x..y] ) {
     printf( "%c", c );
}

will print "a."  This beats the heck out of iterators for most basic 
purposes.  But it leaves me wishing I could operate on reverse ranges 
just as easily.  ie.

foreach( char c; a[y+1..x] ) {
     printf( "%c", c );
}

should print "ba."  This leaves me with one last problem.  I can do:

foreach( char c, a[0..a.length] ) {
     printf( "%c", c );
}

which will print "abc."  But there's no way to refer to the reverse-end 
element.  ie.

foreach( char c, a[a.length..-1] )

I don't like the idea of netagive indexes, but assuming the reverse 
concept goes anywhere there will need to be some way to refer to this 
element for use with foreach.  If this is a bad idea, I suppose we can 
currently fake it:

char[] reverse( char[] src ) {
     char[src.length] dst;
     foreach( int i, char c; src ) {
         dst[src.length-i] = src[i];
     }
     return dst;
}

but it would be nice to avoid the copy if possible.  Comments?


Sean
Feb 22 2004
next sibling parent Sean Kelly <sean ffwd.cx> writes:
Just a quick follow-up.  A class adaptor is another possibility:

class reverse {
public:
     this( char[] src ) {
         m_src = src;
     }
     int opApply( int delegate( inout char ) dg ) {
         for( int i = m_src.length-1; i >= 0; --i ) {
             int r = dg( m_src[i] );
             if( r != 0 ) return r;
         }
         return 0;
     }

private:
     char[] m_src;
};

This might be a bit more difficult for associative ranges, but I think 
still possible.  This being the case, I guess adding a language feature 
really isn't necessary, but I still want it :)


Sean
Feb 22 2004
prev sibling parent "Ben Hinkle" <bhinkle4 juno.com> writes:
"Sean Kelly" <sean ffwd.cx> wrote in message
news:c1b6ad$1ejq$1 digitaldaemon.com...
| First a quick example:
|
| char[] a = "abc";
| int x = 0, y = 1;
| foreach( char c; a[x..y] ) {
|      printf( "%c", c );
| }
|
| will print "a."  This beats the heck out of iterators for most basic
| purposes.  But it leaves me wishing I could operate on reverse ranges
| just as easily.  ie.
|
| foreach( char c; a[y+1..x] ) {
|      printf( "%c", c );
| }
|
| should print "ba."  This leaves me with one last problem.  I can do:
|
| foreach( char c, a[0..a.length] ) {
|      printf( "%c", c );
| }
|
| which will print "abc."  But there's no way to refer to the reverse-end
| element.  ie.
|
| foreach( char c, a[a.length..-1] )
|
| I don't like the idea of netagive indexes, but assuming the reverse
| concept goes anywhere there will need to be some way to refer to this
| element for use with foreach.  If this is a bad idea, I suppose we can
| currently fake it:
|
| char[] reverse( char[] src ) {
|      char[src.length] dst;
|      foreach( int i, char c; src ) {
|          dst[src.length-i] = src[i];
|      }
|      return dst;
| }
|
| but it would be nice to avoid the copy if possible.  Comments?
|
|
| Sean
|

A couple of ideas (both cheesy, but what the hey):

1) foreach( char c, a[x..y].dup.reverse) {...}
2) for(uint i = y; i > x;) { char c = a[--i]; ... }

The trouble is 1 still copies and 2 uses "for", which is
slightly more verbose than "foreach".

-Ben
Feb 22 2004