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
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.
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.
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.
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 Fixnum
s, since they are immutable objects.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With