0

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
Marc Fletcher
  • 932
  • 1
  • 16
  • 39

2 Answers2

3

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
Community
  • 1
  • 1
Hamms
  • 5,016
  • 21
  • 28
  • Typo: 'capitalze!' should be 'capitalize!'. Also, the example is fine, but the select can be made even more concise with: b.select(&:even?) – Keith Bennett Apr 23 '16 at 07:35
  • more concise, yes, but less clear; OP was confused about the nature of the difference between two similarly-named method calls, throwing a new concept like method proccing at them isn't going to do anything but confuse them further. Thanks for the typo catch! – Hamms Apr 24 '16 at 06:47
1

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

Yes. The first one returns a new array. The second one modifies the original array, and returns it.

Is

a.each do |word| word.capitalize! end the same as

a.map do |word| word.capitalize end

No. The first one modifies the elements in the array, and returns the original array. The second one returns a new array filled with new strings.

sawa
  • 165,429
  • 45
  • 277
  • 381