Ruby bug or not?

K

Kevin Olbrich

Using 1.8.4 on OSX.

class CopyTest
attr_accessor :eek:ne
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
 
T

ts

Write it like this

K> class CopyTest
K> attr_accessor :eek:ne

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

K> end

Guy Decoux
 
M

Marcel Molina Jr.

Using 1.8.4 on OSX.

class CopyTest
attr_accessor :eek:ne
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
 
K

Kevin Olbrich

Using 1.8.4 on OSX.

class CopyTest
attr_accessor :eek:ne
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

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,209
Messages
2,571,088
Members
47,687
Latest member
IngridXxj

Latest Threads

Top