[Newbies] Deleting elements from a Collection while looping through it

Levente Uzonyi leves at elte.hu
Sat Dec 10 20:30:05 UTC 2011

On Sat, 10 Dec 2011, Jan Teske wrote:

> Hey,
> I have a question concerning the behavior of Collections in Squeak. Recently 
> I face a problem when trying to delete some elements from a set during a 
> 'do:' message.
> Have a look at this sample method:
>    doFallForAllIn: aSet
>        aSet do:
>            [:block | block fall ifFalse: [aSet remove: block]]
> It loops over a set of blocks and performs the fall message on each of them. 
> If a block is not falling I don't want it to be in aSet after the function 
> returned so I remove it from the set. Squeak doesn't seem to like that since 
> some rather strange error now occures: If a block is removed from the set, 
> the next block in the set will be left out from looping... sometimes. Nearly 
> all the time it works as exspected, only sometimes a block is ignored. I 
> couldn't find any pattern when this happens.
> So my question is: Has anyone an explanation for this? Does the error occure

This happens, because #remove: will rehash elements in the same chain 
after the removed element. The rehashed elements may be moved to a lower 
index, so the loop may not iterate over it at all. You should use 
#removeAllSuchThat: instead. E.g.:

doFallForAllIn: aSet

 	aSet removeAllSuchThat: [ :block | block fall not ]

> because the way I'm doing it is fundamentally wrong? Or am I just overlooking 
> something and it is possible to remove blocks from a collection while looping 
> over it?

As others pointed out, modifying collections while iterating over them is 
not supported in general.


> Thanks in advance!
> _______________________________________________
> Beginners mailing list
> Beginners at lists.squeakfoundation.org
> http://lists.squeakfoundation.org/mailman/listinfo/beginners

More information about the Beginners mailing list