3

I need to know the technical difference between these 2 statements and why it behaves like that:

arr = Array.new(3, "abc")
=> ["abc","abc","abc"]
arr.last.upcase!
=> "ABC"
arr
=>["ABC","ABC","ABC"]     # which is **not** what I excepted

On the other hand:

arr = Array.new(3){"abc"}
=> ["abc","abc","abc"]
arr.last.upcase!
=>"ABC"
arr
=> ["abc","abc","ABC"]     # which is what I excepted
Serjik
  • 10,543
  • 8
  • 61
  • 70
  • From the [documentation](http://www.ruby-doc.org/core-2.1.2/Array.html#class-Array-label-Creating+Arrays): *"Note that the second argument populates the array with references to the same object. Therefore, it is only recommended in cases when you need to instantiate arrays with natively immutable objects such as Symbols, numbers, true or false."* – Stefan Aug 20 '14 at 07:54
  • I'd add, just in case you're a Java programmer, that Ruby strings are mutable objects, not like Java ones. – juanignaciosl Aug 20 '14 at 09:25
  • 1
    I know this is a duplicate (has been asked numerous times already), but SO search is failing me. Anybody have a link at hand? – Jörg W Mittag Aug 20 '14 at 11:38
  • @JörgWMittag, I've had success using Google, with "site:stackoverflow.com" in the search string, when SO's search engine doesn't turn up what I'm looking for. – Cary Swoveland Sep 06 '14 at 05:31
  • [Ruby Array](https://gist.github.com/shanshaji/a5dac2cc28a2f346aff6d6a8c45ae147) – Shan Jul 04 '19 at 06:38

1 Answers1

8

Arguments are always evaluated prior to a method call whereas a block is evaluated only during the method call at a timing controlled by the method (if it is ever evaluated).

In your first example, the argument "abc" is evaluated once before the method new is called. The evaluated object is passed to the method new. The exact same object is used in the all three elements of the created array. Modifying one means modifying all of them.

In your second example, the block {"abc"} is evaluated each time a new element is generated for the array. The three elements in the created array are different objects.

sawa
  • 165,429
  • 45
  • 277
  • 381