Ruby bug or not?

Using 1.8.4 on OSX.

class CopyTest
attr_accessor :one
end

a = CopyTest.new
a.one = [1,2,3,4]
b = a.clone
a.freeze

b.one.each_with_index do |item,index|
b.one.delete_at(index) if item == 2
end

# this is supposed to delete the first item in the array that matches
# instead of all matching items

b.one #=> [1,3,4]

No surprises so far...

a.one #=> [1,3,4]

Now that is weird.

a #=> #<CopyTest:0x35a4ec @one=[1, 3, 4]>
b #=> #<CopyTest:0x348698 @one=[1, 3, 4]>

Not the same object, so why does changing one affect the other?

if you do this....

a.one = [1,2,3,4]
b=a.clone
b.one = [4,3,2,1]

then things work normally
a.one #=> [1,2,3,4]
b.one #=> [4,3,2,1]

I suspect there is a bug in the 'delete_at' function or in the way that
objects are cloned that causes them to refer to the same array in some cases.

Thoughts?

a.one = [1,2,3,4] #=> TypeError: can't modify frozen object

Strange, I also managed to change a frozen object this way.

_Kevin
www.sciwerks.com

···

--
Posted with http://DevLists.com. Sign up and save your mailbox.

b = a.clone

That's not a deep copy:

>> class CopyTest
>> attr_accessor :one
>> end
=> nil
>>
?> a = CopyTest.new
=> #<CopyTest:0x337898>
>> a.one = [1,2,3,4]
=> [1, 2, 3, 4]
>> b = a.clone
=> #<CopyTest:0x32fc4c @one=[1, 2, 3, 4]>
>> a.one.object_id
=> 1673774
>> b.one.object_id
=> 1673774

James Edward Gray II

···

On Aug 15, 2006, at 11:18 AM, Kevin Olbrich wrote:

Write it like this

class CopyTest
attr_accessor :one

    def initialize_copy(obj)
       self.one = obj.one.clone
    end

end

Guy Decoux

a.instance_variable_get(:@one).object_id
=> 177242
b.instance_variable_get(:@one).object_id
=> 177242

The containing instances aren't the same object but they are composed of the
same array object.

Object#clone copies the instance variables of the object being cloned.

marcel

···

On Wed, Aug 16, 2006 at 01:18:21AM +0900, Kevin Olbrich wrote:

Using 1.8.4 on OSX.

class CopyTest
attr_accessor :one
end

a = CopyTest.new
a.one = [1,2,3,4]
b = a.clone
a.freeze

b.one.each_with_index do |item,index|
b.one.delete_at(index) if item == 2
end

# this is supposed to delete the first item in the array that matches
# instead of all matching items

b.one #=> [1,3,4]

No surprises so far...

a.one #=> [1,3,4]

Now that is weird.

a #=> #<CopyTest:0x35a4ec @one=[1, 3, 4]>
b #=> #<CopyTest:0x348698 @one=[1, 3, 4]>

Not the same object, so why does changing one affect the other?

--
Marcel Molina Jr. <marcel@vernix.org>

Yeah, one of those things you figure out right after you post it.

It does concern me that after freezing a, I could modify a.one through b.

I can see that one may not want to have 'freeze' be called recursively
on all instance variables, but it sure did throw me off in this case.

-Kevin

_Kevin
www.sciwerks.com

···

On Wednesday, August 16, 2006, at 1:29 AM, Marcel Molina Jr. wrote:

On Wed, Aug 16, 2006 at 01:18:21AM +0900, Kevin Olbrich wrote:

Using 1.8.4 on OSX.

class CopyTest
attr_accessor :one
end

a = CopyTest.new
a.one = [1,2,3,4]
b = a.clone
a.freeze

b.one.each_with_index do |item,index|
b.one.delete_at(index) if item == 2
end

# this is supposed to delete the first item in the array that matches
# instead of all matching items

b.one #=> [1,3,4]

No surprises so far...

a.one #=> [1,3,4]

Now that is weird.

a #=> #<CopyTest:0x35a4ec @one=[1, 3, 4]>
b #=> #<CopyTest:0x348698 @one=[1, 3, 4]>

Not the same object, so why does changing one affect the other?

a.instance_variable_get(:@one).object_id
=> 177242
b.instance_variable_get(:@one).object_id
=> 177242

The containing instances aren't the same object but they are
composed of the
same array object.

Object#clone copies the instance variables of the object being cloned.

marcel
--
Marcel Molina Jr. <marcel@vernix.org>

--
Posted with http://DevLists.com. Sign up and save your mailbox.