Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Freezing variables in Ruby doesn't work [duplicate]

I am learning Ruby, and I just found interesting behaviour when using the Object#freeze method with variables.

After I freeze a variable (either Fixnum or Array), I am still able to modify it! It is strange, since as far as I am concerned this should not happen and TypeError should be raised.

Here's my code:

test = 666
var = 90
#ok
var += 5

puts "var.frozen? #{var.frozen?}"    
var.freeze    
puts "var.frozen? #{var.frozen?}"

var = test
puts "var = #{var}"

The same is for array:

test = [666]
var = [90]
#ok
var += [5]

puts "var.frozen? #{var.frozen?}"    
var.freeze    
puts "var.frozen? #{var.frozen?}"

var = test
puts "var = #{var}"

But when I try to push something into the array after freezing, it raises an arror, as expected:

test = [666]
var = [90]
#ok
var += [5]

puts "var.frozen? #{var.frozen?}"    
var.freeze    
puts "var.frozen? #{var.frozen?}"

var << test
puts "var = #{var}"

Can somebody explain to me this issue? It seems strange.

Edit I am using Windows XP + Ruby 1.9.3-p429

like image 405
Filip Zymek Avatar asked Jun 12 '13 13:06

Filip Zymek


People also ask

Can you freeze a hash in Ruby?

You can always freeze your hashes in Ruby for safety if you want to. All that's missing is some sugar for declaring immutable hash literals.

What is freeze method in Ruby?

The freeze method in Ruby is used to ensure that an object cannot be modified. This method is a great way to create immutable objects. Any attempt to modify an object that has called the freeze method will result in the program throwing a runtime error. array. array.

What does variable mean in Ruby?

A variable is a name that Ruby associates with a particular object. For example: city = "Toronto" Here Ruby associates the string "Toronto" with the name (variable) city. Think of it as Ruby making two tables. One with objects and another with names for them.


2 Answers

You freeze objects, not variables, i.e. you can't update a frozen object but you can assign a new object to the same variable. Consider this:

a = [1,2,3]
a.freeze
a << 4
# RuntimeError: can't modify frozen Array

# `b` and `a` references the same frozen object
b = a
b << 4    
# RuntimeError: can't modify frozen Array

# You can replace the object referenced by `a` with an unfrozen one
a = [4, 5, 6]
a << 7
# => [4, 5, 6, 7]

As an aside: it is quite useless to freeze Fixnums, since they are immutable objects.

like image 80
toro2k Avatar answered Sep 28 '22 10:09

toro2k


In Ruby, variables are references to objects. You freeze the object, not the variable.

Please note also that

a = [1, 2]
a.freeze
a += [3]

is not an error because + for arrays creates a new object.

like image 28
undur_gongor Avatar answered Sep 28 '22 12:09

undur_gongor