Iterating over containers of immutable objects

Steven Schveighoffer schveiguy at yahoo.com
Tue Jun 29 14:39:56 PDT 2010


On Tue, 29 Jun 2010 17:07:40 -0400, Justin Johansson <no at spam.com> wrote:

> To cut to the chase, what is the idiomatic code for iterating
> over a container of immutable objects when the container provides
> a "getIterator" method?
>
> Alternatively, how can the following code be written
> (1) to not use a break statement and,
> (2) with casting away immutability.
>
> Specifically my question is about assigning to an
> immutable loop variable and not wanting to get
> into any discussion about iterators and ranges per
> se (unless relevant to the first bit).
>
>
> // A class reprenting some abstract immutable item
> immutable abstract class Bar
> {
> }
>
> // A container of Bar immutable objects
> abstract class BarContainer
> {
>     BarIterator getIterator();
> }
>
> // An interface for iterating over the
> // immutable Bar objects in a BarContainer
> interface BarIterator
> {
>     immutable(Bar) next();
> }
>
> void testBarIterator( BarContainer barContainer)
> {
>     auto iter = barContainer.getIterator();
>
>     while (true) {
>        auto bar = iter.next();
>
>        if (bar is null)
>           break;
>
>        // process the bar item
>        // ...
>     }
> }
>
>
> So far so good, but having the break statement doesn't
> seem all that clean.  My next try appeals better in style
> to me but it doesn't compile, yielding
>
> Error: variable test.testBarIterator2.bar cannot modify immutable
>
> void testBarIterator2( BarContainer barContainer)
> {
>     auto iter = barContainer.getIterator();
>     immutable Bar bar;
>
>     while ((bar = iter.next()) !is null) {	// error line
>        // process the bar item
>        // ...
>     }
> }
>
>
> Probably I've missed something but the answer alludes me.


You missed your old friend opApply :)

interface BarIterator
{
    int opApply(int delegate(ref immutable(Bar)) dg);
}

void testBarIterator(BarContainer barContainer)
{
    foreach(bar; barContainer.getIterator())
    {
       // process the bar item
    }
}

But this is an indirect response to your question.  The real problem is  
lack of tail-const support for classes.  You can use Rebindable in  
std.typecons to get a rebindable const or immutable class reference.   
IIRC, it's severely out of date (still uses opDot), but that's what we got.

-Steve


More information about the Digitalmars-d mailing list