Thread overview
foreach, slices, and reverse ranges
Feb 22, 2004
Sean Kelly
Feb 22, 2004
Sean Kelly
Feb 22, 2004
Ben Hinkle
February 22, 2004
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

February 22, 2004
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

February 22, 2004
"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