Will Ashley Will Ashley - 7 months ago 27
Ruby Question

Ruby Array mutation confusion?

I'm trying to get very comfortable with all of the array methods and enumerables in Ruby, but I don't understand why some don't mutate and others do. For instance, is there a difference between:

def double(array)
array.map {|x| x * 2}
end


and

def double(array)
return array.map! {|x| x * 2}
end


Also, when I tried to call

b.select{|x| x.even?}


where b is an array of integers, it did not change, but

b = b.select{|x| x.even?} OR
.delete_if


did seem to mutate it.

Is

a.each do |word|
word.capitalize!
end


the same as

a.map do |word|
word.capitalize
end

Answer

As a rule of thumb, ruby methods that end in ! will mutate the value they are called on, and methods without will return a mutated copy.

See here the documentation for map vs map! and capitalize vs capitalize!

Also note that b = b.select{|x| x.even?} is not mutating the list b, but is rather calling b.select to create an entirely new list, and assigning that list to b. Note the difference:

In this, b is the same object, just changed:

$ irb
@irb(main):001:0> b = [1,2,3]
=> [1, 2, 3]
@irb(main):002:0> b.object_id
=> 69853754998860
@irb(main):003:0> b.select!{|x| x.even?}
=> [2]
@irb(main):004:0> b.object_id
=> 69853754998860

But in this, b is now an entirely new object:

$ irb
@irb(main):001:0> b = [1,2,3]
=> [1, 2, 3]
@irb(main):002:0> b.object_id
=> 70171913541500
@irb(main):003:0> b = b.select{|x| x.even?}
=> [2]
@irb(main):004:0> b.object_id
=> 70171913502160