Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

+= operator appears to modify frozen string

Tags:

I am using ruby freeze method. As far as the definition of freeze is considered, it freezes the value of the object on which it is called. We can not modify the value of that object after it. I have to achieve same task, I have a an object and I am executing following code

a = "Test" a.freeze a += "this string" puts a 

This gives outputs as follows:

Test this string [Finished in 0.0s] 

Why it is modifying my frozen string?

like image 548
Akshay Neema Avatar asked Dec 29 '16 08:12

Akshay Neema


2 Answers

Nothing is modifying your frozen String

You are re-assigning a to a new String with

a += "this string" 

which is internally the same in Ruby as

a = a + "this string" 

When you add two String objects in Ruby, it will create a new String containing the result (this is normal behaviour for + operator on most objects that support it). That leaves the original "Test" and "this string" values unchanged. The original, frozen String (containing "Test") will remain in memory until it is garbage collected. It can be collected because you have lost all references to it.

If you attempted to modify the object in place like this:

a << "this string" 

then you should see an error message RuntimeError: can't modify frozen String

Basically, you have confused a, the local variable, with the String object to which it is pointing. Local variables can be re-assigned at any time, independently of the objects stored by Ruby. You can verify this is what has happened in your case by inspecting a.object_id before and after your a +=... line.

like image 114
Neil Slater Avatar answered Sep 19 '22 15:09

Neil Slater


The freeze method prevents you from changing an object, it turns an object into a constant.

s1 = "its testing" s1.freeze puts "Object ID ===", s1.obejct_id 

So, after freezing an object, an attempt to modify it results in TypeError.

s1 << "testing again" 

it will give, RuntimeError: can't modify frozen String

BUT,

freeze operates on an object reference, not on a variable

s1 += "New Testing" puts "Object ID ===", s1.obejct_id 

will point to evaluated to a new object and also check its object ID.

For detailed information refer this site, http://rubylearning.com/satishtalim/mutable_and_immutable_objects.html

like image 33
Mansi Shah Avatar answered Sep 19 '22 15:09

Mansi Shah