# Problem with Array#delete?

**URL:** <https://www.ruby-forum.com/t/problem-with-array-delete/141354>\
**Category:** Ruby\
**Created:** [June 24, 2008, 10:46pm UTC](https://www.ruby-forum.com/t/problem-with-array-delete/141354 "2008-06-24T22:46:26Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [June 24, 2008, 10:46pm UTC](https://www.ruby-forum.com/t/problem-with-array-delete/141354/1 "2008-06-24T22:46:26Z")

</div>

Hi all,

In messing around with Array#delete I think I’ve uncovered a problem.  
Consider this example:

class Foo  
def ==(other)  
$array.clear  
false  
end  
end

arr = [1, 2, 3]  
arr \<\< Foo.new  
Arr \<\< ‘b’

$array = arr

arr.delete(‘a’)

p arr # =\> []  
p $array # =\> []

That’s what I would expect. It did the comparison, and called the  
Foo#== method, which in turn cleared the receiver.

But if you do this instead:

arr.delete(1)

You end up with:

[nil, nil, #Foo:0x2865ff4]  
[nil, nil, #Foo:0x2865ff4]

What’s happening?

Thanks,

Dan

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [June 24, 2008, 11:56pm UTC](https://www.ruby-forum.com/t/problem-with-array-delete/141354/2 "2008-06-24T23:56:06Z")

</div>

On Tue, Jun 24, 2008 at 4:43 PM, Daniel B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> end  
> p $array # =\> []  
> [nil, nil, #Foo:0x2865ff4]  
> [nil, nil, #Foo:0x2865ff4]
> 
> What’s happening?

Well, I haven’t dug into the implementation of Array#delete enough to  
fully  
explain the results but.

You do know that after the assignment

$array = arr

You’ve made the global variable $array reference the same object to  
which  
you are sending delete.

So the $array.clear in the Foo#== method is clearing that object which  
is  
the receiver of the delete method.

Now in general ruby iterator methods don’t expect the enumerated object  
to  
change during the iteration and that’s just what’s happening.

This is no doubt confusing the delete method.

–  
Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [June 25, 2008, 12:32am UTC](https://www.ruby-forum.com/t/problem-with-array-delete/141354/3 "2008-06-25T00:32:21Z")

</div>

On Tue, Jun 24, 2008 at 5:53 PM, Rick DeNatale [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> Well, I haven’t dug into the implementation of Array#delete enough to fully  
> explain the results but.

And having now looked at the Ruby 1.8 implementation of Array#delete, I  
think I know exactly what’s going on.

Here’s a pseudo-ruby translation of the C code:

class Array  
def delete(obj)  
i1 = i2 = 0  
while i1 \< self.length  
e = self[i1]  
unless e == obj  
self[i2] = e  
i2 += 1  
end  
i1 += 1  
end  
if i2 = self.length # We didn’t find any matches  
return yield(obj) if block\_given?  
else  
self.length = i2  
end  
end

```
def length=(l)
    # A method to set the length of the array and make any necessary

```

internal adjustments  
end  
end

So, you start out with arr = $array = [1, 2, 3, aFoo, ‘b’]

And then call  
arr.delete(1)

Now lets’s step through the delete method

i1 i2 self e e == 1  
Action  
0 0 [1, 2, 3, aFoo, ‘b’] 1 true so we  
just  
increment i1 giving  
1 0 [1, 2, 3, aFoo, ‘b’] 2 false so we  
change self[i0] and increment i2 giving  
2 1 [2, 2, 3, aFoo, ‘b’] 3 false so we  
change  
self[i0] and increment i2 giving  
3 2 [2, 3, 3, aFoo, ‘b’] Foo BANG! this clears  
$array which is also self which is also arr, since all reference the  
same  
object. The state is now:  
3 2 [nil, nil, nil, nil] Foo false  
Foo#==  
returns false so we set self[i2] = e and increment i2 giving:  
4 3 [nil, nil, aFoo, nil]

# And the loop ends and self.length = 3 adjusts things so that self == arr

$array == [nil, nil, aFoo]

–  
Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)
