How to check if a Ruby object is immutable?

Is there an easy way to check if an object is immutable (numbers, zero) or not (Array, Hash, objects)? In other words, can it be altered by side effects from another code?

Motivation: I want to create a repository with versions, but some of them are arrays. Some of the arrays will store user objects, and I could invert the relationship by saving the "in" property and doing a search. But I would also like to be able to store arrays of characters, other arrays, etc.

+4
source share
4 answers

There are no primitive objects in Ruby. Therefore, it is impossible to detect in a simple way.

Can't you use marshal or YAML for your version store? You will then receive a free download and save of all types of objects. Why reinvent the wheel?

I donโ€™t know what you want to achieve exactly, but looking at the source of YAML, it may be interesting to see how they deal with this problem. Implementing Ruby Coding YAML simply implements the to_yaml method for all relevant classes. See yaml / rubytypes.rb .

+4
source

I found an inefficient way:

 class Object def primitive? begin self.dup false rescue TypeError true end end end 
+6
source

The idea of โ€‹โ€‹mutability is not really applied in Ruby in the same way as in other languages. The only immutable object is frozen. You can even add instance methods and variables to Fixnums. For instance:

 class Fixnum attr_accessor :name end 1.name = "one" 2.name = "two" 

Obviously, the vast majority of the time, people will not be pathological enough to add attributes to Fixnum, but the fact is that an unfrozen object is truly unchanged.

If you can come up with a canonical list of classes that you want to accept, they are immutable, you can just go through and give them all the immutable?() Method, which returns true (and Object a version, which returns false). But, as wvanbergen said, the best way to make sure your copy of an object is not changing is to copy it deeply with the marshal.

+2
source

Another difference: immutable objects cannot be frozen, but they still return false from frozen?

 5.freeze.frozen? == false 

Freeze does not throw an exception (unlike dup) However, it (constantly!) Modifies mutable objects.

I found that I can (at least in the current state) host my application for working with frozen objects, and ruby โ€‹โ€‹will give me an exception if I try to change them directly. However, freezing affects only the first level of the object , and the arrays, etc. stored in it, can still be changed.

Does this apply only to 1.8 - 5.frozen? returns true in ruby1.9 (but not in irb1.9)

0
source

All Articles