1

I'm having difficulty seeing how the processes for creating the value for a new instance of a String object differs from creating the value for a String literal.

a = String.new("Hello")
# => "Hello"

b = "Hello"
# => "Hello"

and if I run

a == b
# => true

Same values! What's going on?

1
  • 3
    str = "oh, my" is shorthand for String.new("oh, my"), almost. See String#new for the differences, which involve encoding. Generally, the literal assignment is used. Commented Jan 12, 2017 at 0:14

4 Answers 4

4

A string literal is a string object. There's no difference in earlier versions of Ruby.

As of Ruby 2.3 you have the option to have string literals frozen. It's the planned default in Ruby 3.0

this means that...

x = "Hello"
x.upcase!

...will generate an error, because the string is not mutable.

Using the constructor...

x = String.new("Hello")
x.upcase!

Works fine.

Sign up to request clarification or add additional context in comments.

Comments

3

== checks for equal content.

equal? checks for equal identity.

a = "hello"
b = "hello"

a == b # => true
a.equal?(b) # => false

In Ruby string literals are not immutable and thus creating a string and using a literal are indeed the same. In both cases Ruby creates a new string instance each time the expressions in evaluated.

Both of these are thus the same

10.times { String.new }
# is the same as
10.times { "" }

Let's verify this

10.times { puts "".object_id }

Prints 10 different numbers

70227981403600
70227981403520
70227981403460
...

Why? Strings are by default mutable and thus Ruby has to create a copy each time a string literal is reached in the source code. Even if those literals are usually rarely modified in practice.

Thus a Ruby program typically creates an excessive amount short-lived string objects, which puts a huge strain on garbage collection. It is not unusual that a Rails app creates 500,000 short-lived strings just to serve one request and this is one of the main performance bottlenecks of scaling Rails to millions or even 100 millions of users.

To address that Ruby 2.3 introduced frozen string literals, where all string literals default to being immutable. Since this is not backwards compatible it is opt-in with a pragma

# frozen_string_literal: true

Let's verify this too

# frozen_string_literal: true
10.times { puts "".object_id }

Prints the same number 10 times

69898321746880
69898321746880
69898321746880
...

Fun fact, setting a key in a hash also creates a copy of a string

str = "key"
hash = {}
hash[str] = true
puts str.object_id
puts hash.keys.first.object_id

Prints two different numbers

70243164028580
70243132639660

Comments

1

In your example a and b are c-like references and not pointers. So you are comparing values not objects.

Comments

1

Same values! What's going on?

Nothing special going on, you can create infinite number of local variables with same value.

You can use Object#object_id to see, that these variables are in fact different objects:

a = String.new("Hello")
b = "Hello"
a.object_id #=> 70295696460580
b.object_id #=> 70295696294220

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.