8 ms·
You're missing a few details, especially around "primitive" data types. There's not really any such thing in Ruby - everything is an object, but some objects -
by jcoglan 16y ago
You're missing a few details, especially around "primitive" data types. There's not really any such thing in Ruby - everything is an object, but some objects - numbers, booleans, nil - are immutable.
When you copy an object, all you do is copy its set of instance variables, which are just references to other objects. For an array, the instance variables are its set of indexes, which again are just references. Copying an array just means making a new list of references, but the objects they point to remain unmodified and uncopied.
Consider:
<pre>
array = ["foo"]
copy = array.dup
</pre>
array and copy are independently mutable - modifying the index in one does not affect the indexes in the other - but they still both contain references to the single string "foo". Thus:
<pre>
copy.first.gsub! /foo/, "bar"
</pre>
modifies the string referenced by copy, which is the same string referenced by array. So array becomes ["bar"].
If you want a true deep copy, do something like this:
<pre>
def deep_copy(object)
case object
when Array
object.map { |item| deep_copy(item) }
when Hash
object.inject({}) do |hash, (key,value)|
hash[deep_copy(key)] = deep_copy(value)
hash
end
# handle other data structures if need be
else
object.respond_to?(:dup) ? object.dup : object
end
end
</pre>
- jcoglan 16y agoApologies for the formatting screw-up. The deep_copy function is here: http://gist.github.com/407741 http://gist.github.com/407741
- aarongough 16y agoNo worries, thanks for taking the time to write it out. I'm glad that I wrote the post (and that I'm getting hammered a little for my assumptions) because making mistakes is probably the only way I'm going to get a deeper understanding of the language... One thing that confused the issue a little for me is the fact that some objects in Ruby are actually only really 'pretend objects'. ie: >> test = 4 => 4 >> test2 = 4 => 4 >> test.object_id => 9 >> test2.object_id => 9 I don't know enough about the deeper parts of the language to know what else there is that's like this though...
- bschaefer 16y agoThis is a performance optimization for common (read: integer) numbers: http://ruby-doc.org/core/classes/Fixnum.html http://ruby-doc.org/core/classes/Fixnum.html >> ((1 << 30) - 1).class => Fixnum >> ((1 << 30)).class => Bignum >> ((1 << 30) - 1).object_id => 2147483647 >> ((1 << 30) - 1).object_id => 2147483647 >> (1<<30).object_id => 166070 >> (1<<30).object_id => 161200