43

Consider the following code:

$ irb
> s = "asd"
> s.object_id   # prints 2171223360
> s[0] = ?z     # s is now "zsd"
> s.object_id   # prints 2171223360 (same as before)
> s += "hello"  # s is now "zsdhello"
> s.object_id   # prints 2171224560 (now it's different)

Seems like individual characters can be changed w/o creating a new string. However appending to the string apparently creates a new string.

Are strings in Ruby mutable?

SundayMonday
  • 19,147
  • 29
  • 100
  • 154
  • 2
    Yes, and answerable via trivial search. http://stackoverflow.com/questions/2608493/why-did-matz-choose-to-make-strings-mutable-by-default-in-ruby – Dave Newton Dec 20 '11 at 18:43
  • @DaveNewton: Isn't it great how easy it is to find dups on SO as you can almost count on an SO topic coming up first on google? – Ed S. Dec 20 '11 at 18:45
  • 4
    `+` is Concatenating and will return a new string. `<<` is Appending and will append to the given string object (not create a new one). – Chad Dec 20 '11 at 18:45
  • @EdS. Yes and no; yes because it's been answered, no because it means people would rather just ask a question than do even a modest amount of research. – Dave Newton Dec 20 '11 at 18:46
  • 2
    `s += "hello"` is shorthand for `s = s + "hello"`, which runs the `String#+` method, which always returns a new string. – Alex Wayne Dec 20 '11 at 18:46
  • @DaveNewton: Well, great for us who close topics and answer questions I suppose. – Ed S. Dec 20 '11 at 18:49

6 Answers6

54

Yes, strings in Ruby, unlike in Python, are mutable.

s += "hello" is not appending "hello" to s - an entirely new string object gets created. To append to a string 'in place', use <<, like in:

s = "hello"
s << "   world"
s # hello world
Marek Příhoda
  • 11,108
  • 3
  • 39
  • 53
  • 4
    Does it make sense to think of `a += b` as `a = a + b` in Ruby? That would make it clear why `s += "hello"` creates a new string. – Emil Laine Jan 08 '16 at 17:52
  • 3
    @tuple_cat Yes, that's how `+=` is implemented, thus redefining `+` yields a redefined `+=`. – YoTengoUnLCD Jul 12 '16 at 19:08
17
ruby-1.9.3-p0 :026 > s="foo"
 => "foo" 
ruby-1.9.3-p0 :027 > s.object_id
 => 70120944881780 
ruby-1.9.3-p0 :028 > s<<"bar"
 => "foobar" 
ruby-1.9.3-p0 :029 > s.object_id
 => 70120944881780 
ruby-1.9.3-p0 :031 > s+="xxx"
 => "foobarxxx" 
ruby-1.9.3-p0 :032 > s.object_id
 => 70120961479860 

so, Strings are mutable, but += operator creates a new String. << keeps old

zed_0xff
  • 32,417
  • 7
  • 53
  • 72
10

Appending in Ruby String is not +=, it is <<

So if you change += to << your question gets addressed by itself

Oleg Mikheev
  • 17,186
  • 14
  • 73
  • 95
  • 3
    +1. As explained at http://www.rubyfleebie.com/appending-to-a-string/, "`+=` will create a new String instance and will assign it to your left object. On the other hand, `<<` will append the new string directly into your already existing left object." – ruakh Dec 20 '11 at 18:45
9

Strings in Ruby are mutable, but you can change it with freezing.

irb(main):001:0> s = "foo".freeze
=> "foo"
irb(main):002:0> s << "bar"
RuntimeError: can't modify frozen String
hipertracker
  • 2,425
  • 26
  • 16
2

Ruby Strings are mutable. But you need to use << for concatenation rather than +.
In fact concatenating string with
+ operator(immutable) because it creates new string object.
<< operator(mutable) because it changes in the same object.

Faruk Hossen
  • 185
  • 1
  • 8
1

From what I can make of this pull request, it will become possible in Ruby 3.0 to add a "magic comment" that will make all string immutable, rather than mutable.

Because it seems you have to explicitly add this comment, it seems like the answer to "are string mutable by default?" will still be yes, but a sort of conditional yes - depends on whether you wrote the magic comment into your script or not.

EDIT

I was pointed to this bug/issue on Ruby-Lang.org that definitively states that some type of strings in Ruby 3.0 will in fact be immutable by default.

sameers
  • 4,855
  • 3
  • 35
  • 44