Changes to x within x.each()

Does Ruby have defined behavior for ‘each’ in the following:

x.each do |obj|
    ...
    x.change()    # This may add or remove objects from x
end

Cases:

  1. Adding or removing objects ‘before’ obj.
  2. Adding or removing objects ‘after’ obj.

I’m primarily interested when x is an array.

On Jun 28, 2006, at 11:20 PM, Jim V. Tess wrote:

I’m primarily interested when x is an array.


Posted via http://www.ruby-forum.com/.

As far as I know theres not explicitly defined behavior, but I
believe 2) works as you might expect.

On 6/29/06, Jim V. Tess [email protected] wrote:

I’m primarily interested when x is an array.

From experience Ruby keeps an array index to do each, so if something
inserted after obj it’ll work, but something before will cause each to
get obj twice.

On 29/06/06, Phillip H. [email protected] wrote:

From experience Ruby keeps an array index to do each, so if something
inserted after obj it’ll work, but something before will cause each to
get obj twice.

Yep. You can see this in the ‘why do only half the elements from my
array get deleted?’ problem:

array = %w[a b c d e f g h i j k]
array.each do |e|
array.delete(e)
end
array # => [“b”, “d”, “f”, “h”, “j”]

Paul.

2006/6/29, Phillip H. [email protected]:

From experience Ruby keeps an array index to do each, so if something
inserted after obj it’ll work, but something before will cause each to
get obj twice.

Personally I wouldn’t rely on this behavior though. Changing a
collection while iterating it often leads to undefined behavior.
Personally I’d rather choose an approach that either copies the
collection or defers the changes to after the iteration. Alternatively
with an array iterate explicitely with for and using an array index.

ar = ar.inject([]) {|copy, el|
case x
when “add”
then copy << el << “bar”
when “remove”
then copy
else
copy << el
end
end

Kind regards

robert