1

How come concatenating to a string does not change its object_id? My understand was that Strings are immutable because Strings are essentally Arrays of Characters, and Arrays cannot be changed in memory since they are contiguous. Yet, as demonstrated below: Instantiating a String than adding characters does not change it's object_id. How does concatenation effect the String in memory?

2.1.2 :131 > t1 = "Hello "
 => "Hello "
2.1.2 :132 > t1.object_id
 => 70282949828720
2.1.2 :133 > t2 = t1
 => "Hello "
2.1.2 :134 > t2.object_id
 => 70282949828720
2.1.2 :135 > t2 << "HEY THERE MATE"
 => "Hello HEY THERE MATE"
2.1.2 :136 > t2.object_id
 => 70282949828720
2.1.2 :137 > t1.object_id
 => 70282949828720
2.1.2 :138 >
chopper draw lion4
  • 12,401
  • 13
  • 53
  • 100

2 Answers2

4

How come concatenating to a string does not change its object_id?

Because it's still the same string it was before.

My understand was that Strings are immutable

No, they are not immutable. In Ruby, strings are mutable.

because Strings are essentally Arrays of Characters,

They are not. In Ruby, strings are mostly a factory for iterators (each_line, each_char, each_codepoint, each_byte). It implements a subset of the Array protocol, but that does not mean that it is an array.

and Arrays cannot be changed in memory since they are contiguous.

Wrong, arrays are mutable in Ruby.

Yet, as demonstrated below: Instantiating a String than adding characters does not change it's object_id. How does concatenation effect the String in memory?

The Ruby Language Specification does not prescribe any particular in-memory representation of strings. Any representation is fine, as long as it supports the semantics specified in the Ruby Language Specification.

Here's a couple of examples from some Ruby implementations:

Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
1

Ruby strings are not immutable, in contrast to languages like Python and Java. The underlying char array is internally resized to accommodate the appended characters.

If you want an immutable string in ruby (for example, Bad Things can happen if you use a mutable value as a hash key), use a symbol:

my_sym = :foo

or

my_sym = my_string.to_sym
jjm
  • 6,028
  • 2
  • 24
  • 27
  • So, the Ruby String class is a wrapper over an Array. And when an instance of the String class needs to be resized it instantiates a new array, but the Ruby object itself never actually changes, just references a different array internally. Is that accurate? – chopper draw lion4 Nov 30 '14 at 02:42
  • 1
    Yeah, it's all implemented in C, of course, and the array is a member of a C struct representing the string, so it has a fixed size. It's reallocated when it needs to grow, typically doubling in size (so that the number of reallocations is the log of the string length). If you're interested, the actual implementation is here: https://github.com/ruby/ruby/blob/trunk/string.c. It's super complicated, but the basic idea is the one I described. – jjm Nov 30 '14 at 03:03
  • To create an immutable string you can also [freeze](http://rubylearning.com/satishtalim/mutable_and_immutable_objects.html) it – Uri Agassi Dec 02 '14 at 07:51
  • True, for some reason I was under the impression that freeze and to_sym did the same thing. The difference is that to_sym will convert the string to an existing symbol, whereas freeze will simply make it immutable. – jjm Dec 02 '14 at 17:48