Bug #14641
closedShouldn't Array#map not modify its array?
Description
Hi,
Thanks for the awesome work you guys have been doing on Ruby for all this years.
I might be missing something obvious, but I thought Array#map doesn't modify the array it's called on?
Ie.
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux]
a = ['a','b']
..
=> ["a", "b"]
a.map{|e| e << 'c'}
=> ["ac", "bc"]
a.map{|e| e << 'c'}
=> ["acc", "bcc"]
a.map{|e| e << 'c'}
=> ["accc", "bccc"]
a.map{|e| e << 'c'}
=> ["acccc", "bcccc"]
a
=> ["acccc", "bcccc"]
Expected a
to be still ["a", "b"].
Same in Ruby 2.4 ruby 2.4.2p198 (2017-09-14 revision 59899) [x86_64-darwin16]
irb(main):003:0* a = ['a','b']
=> ["a", "b"]
irb(main):004:0> a.map{|e| e << 'c'}
=> ["ac", "bc"]
irb(main):005:0> a.map{|e| e << 'c'}
=> ["acc", "bcc"]
irb(main):006:0> a.map{|e| e << 'c'}
=> ["accc", "bccc"]
irb(main):007:0> a.map{|e| e << 'c'}
=> ["acccc", "bcccc"]
irb(main):008:0> a
=> ["acccc", "bcccc"]
Thanks for you guys time.
Updated by jeremyevans0 (Jeremy Evans) over 6 years ago
- Status changed from Open to Rejected
The array itself is not modified, you are mutating elements of the current array during iteration (as String#<< mutates the receiver), then returning a new array with the mutated elements (since String#<< returns the receiver). If you don't want to mutate the elements, use String#+:
irb(main):001:0> a = ['a', 'b']
=> ["a", "b"]
irb(main):002:0> a.map{|e| e + 'c'}
=> ["ac", "bc"]
irb(main):003:0> a
=> ["a", "b"]
irb(main):004:0> a.object_id
=> 11790377160340
irb(main):005:0> a.map{|e| e << 'c'}.object_id
=> 11788696580840
Updated by hartator (Julien Khaleghy) over 6 years ago
jeremyevans0 (Jeremy Evans) wrote:
The array itself is not modified, you are mutating elements of the current array during iteration (as String#<< mutates the receiver), then returning a new array with the mutated elements (since String#<< returns the receiver). If you don't want to mutate the elements, use String#+:
irb(main):001:0> a = ['a', 'b'] => ["a", "b"] irb(main):002:0> a.map{|e| e + 'c'} => ["ac", "bc"] irb(main):003:0> a => ["a", "b"] irb(main):004:0> a.object_id => 11790377160340 irb(main):005:0> a.map{|e| e << 'c'}.object_id => 11788696580840
It was my bad. Thanks for the explanation, Jeremy.