Ruby strings are mutable objects

A string literal like "hello" is stored in a read-only memory segment and represented internally as an array of characters terminated by a null byte ('\0').

 0x17 . . . . . . . . . . . . . 0x1c
--------------------------------------
| 'h' | 'e' | 'l' | 'l' | 'o' | '\0' |
--------------------------------------

Since it’s read-only, we can retrieve values using the index operator (Index operator is used for constant time look-up), but we cannot modify its contents.

char *str = "hello";
printf("%c\n", str[0]); // 'h'

str[0] = 'H'; // Undefined Behavior
printf("%s\n", str); // likely cause an error

In Ruby, however, this works perfectly fine. It’s a valid code.

str = "hello"
str[0] = 'H'

str # => "Hello"

The reason being is that, strings in Ruby are actually mutable objects not immutable ([[Everything is an object in Ruby]]). Under the hood, it’s creating an instance of a string object that internally stores a mutable sequence of characters, allowing array-like behavior. So, str = "hello" is actually equivalent to String.new("hello").

If you want to simulate a string literal in Ruby where you cannot modify its contents, you can use freeze.

str = "hello".freeze
str[0] = 'H' # FrozenError (can't modify frozen String)
Backlinks: