Bug or not a bug? array*=int

K

Kyle Schmitt

So I'm wondering, is this a bug, or not a bug, or a type-o in the docs?

According to http://www.ruby-doc.org/core/classes/Array.html
array*int "[R]eturns a new array built by concatenating the int
copies of self."
Copies should be brand new independent copies, right?

foo=[[nil,nil,nil]]returns a new array built by concatenating the int
copies of self.
foo*=3
#Foo is now.
#[[nil,nil,nil],
# [nil,nil,nil],
# [nil,nil,nil]]

foo[1][1]=12
#Foo is now
#[[nil,12,nil],
# [nil,12,nil],
# [nil,12,nil]]

#But I would have expected it to be
#[[nil,nil,nil],
# [nil,12,nil],
# [nil,nil,nil]]
 
M

Martin DeMello

So I'm wondering, is this a bug, or not a bug, or a type-o in the docs?

According to http://www.ruby-doc.org/core/classes/Array.html
array*int "[R]eturns a new array built by concatenating the int
copies of self."
Copies should be brand new independent copies, right?

No, copies are shallow copies. Consider, for example

irb(main):002:0> class A; attr_accessor :a; end
=> nil
irb(main):003:0> a = A.new
=> #<A:0xb7c65b44>
irb(main):004:0> a.a = 10
=> 10
irb(main):005:0> foo = [a]
=> [#<A:0xb7c65b44 @a=10>]
irb(main):006:0> foo *= 3
=> [#<A:0xb7c65b44 @a=10>, #<A:0xb7c65b44 @a=10>, #<A:0xb7c65b44 @a=10>]
irb(main):007:0> a.a = 20
=> 20
irb(main):008:0> foo
=> [#<A:0xb7c65b44 @a=20>, #<A:0xb7c65b44 @a=20>, #<A:0xb7c65b44 @a=20>]

martin
 
K

Kyle Schmitt

Ahh.
And upon not being lazy and looking at the C, I see this...
ary2 = ary_new(rb_obj_class(ary), len);

Which I'm guessing is equivalent to this in ruby (which I already knew
would return the same array len times)
ary2=Array.new(ary,len)

Any chance the document maintainer could slip the word "shallow" into
the description of array*?

:)
 
R

Robert Klemme

Ahh.
And upon not being lazy and looking at the C, I see this...
ary2 = ary_new(rb_obj_class(ary), len);

Which I'm guessing is equivalent to this in ruby (which I already knew
would return the same array len times)
ary2=Array.new(ary,len)

Any chance the document maintainer could slip the word "shallow" into
the description of array*?

Dunno. But all (or almost all) copies (e.g. dup, clone, Enumerable#map,
Enumerable#select) do shallow copying only. So shallow is the rule and
not particularly exceptional - as it is also more efficient and deep
copy is more complex (i.e. deciding when to create a new object or just
copy the reference). There are quite a few discussions of this topic in
the archives...

For deep copies the idiom probably most often used is

copy = Marshal.load(Marshal.dump(obj))

Kind regards

robert
 
S

Stefan Rusterholz

Kyle said:
Ahh.
And upon not being lazy and looking at the C, I see this...
ary2 = ary_new(rb_obj_class(ary), len);

Which I'm guessing is equivalent to this in ruby (which I already knew
would return the same array len times)
ary2=Array.new(ary,len)

Any chance the document maintainer could slip the word "shallow" into
the description of array*?

:)

As mentioned by others, shallow is the default (also to my knowledge in
most OO languages).
The moment you wish for deep copy is usually the moment you should
consider writing a proper class instead of deeply nesting
arrays/hashes/...

Regards
Stefan
 
K

Kyle Schmitt

As mentioned by others, shallow is the default (also to my knowledge in
most OO languages).
The moment you wish for deep copy is usually the moment you should
consider writing a proper class instead of deeply nesting
arrays/hashes/...

Regards
Stefan

Stefan, while I agree that in general you should write a proper class,
the case I was talking about is a completely valid and normal use of
multi-dimensional arrays in ruby. I'm guessing that duplicating a row
in an array is not a rare occurrence either. I was just saying that
maybe a mention of this should be added to the standard docs, as it's
a common pitfall. Bits are cheap :) common pitfalls should be noted
all over the place in the docs.

--Kyle
 

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

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,825
Latest member
VernonQuy6

Latest Threads

Top