Shallow Copies & Deep Copies
I spent a few hours this afternoon pairing with [Jeremy](http://jneander.github.com/) on the project he's been working on (with several of the other resident apprentices). Because I don't know Clojure, I wasn't *pairing* as much as I was observing Jeremy, asking questions, and listening to him explain his thought process and a few nuances of Clojure. As we were talking, the concept of shallow copies and deep copies came up. While I had heard the terms before, I didn't have a clear understanding of their meaning. For example, I wouldn't have felt comfortable explaining them to someone else. When you make a shallow copy it copies each of the member field values. *Example:* person = {:name => "Kyrie", :occupation => "baller"} person_copy = person So now I'm thinking I have a copy of `person` and I can play around with it and my original should remain untouched. person_copy[:occupation] = "trapeze artist" # person_copy is now: {:name=>"Kyrie", :occupation=>"trapeze artist"} # person is also now: {:name=>"Kyrie", :occupation=>"trapeze artist"} What happened? Certain types (symbols, true/false, integers, and others) are immediate values. When you reference one of these types with a variable, in Ruby the variable stores the value directly. When a Fixnum object is passed in as an argument, the actual object is passed (not a reference to that object). With complex objects (like my hash), it stores a reference to the value object. It just got copied as a reference to the original object. Let's see how it's different with integers. *Example:* number = 3 number_copy = number # number is 3 # number_copy is 3 number_copy = 14 # number_copy is now 14 # number is still 3 In Ruby, we have two methods, `dup` and `clone`, that are used to create shallow copies. With shallow copies, modifying one (the original or the copy) will alter the other. Both are sharing the same data. Executing shallow copies is faster though. `dup` and `clone` are slightly different. baseball = Object.new def baseball.throw puts "THROW" end print baseball.throw # => "THROW" another_baseball = baseball.dup print another_baseball.throw # => NoMethodError `clone` does two things `dup` cannot do. It copies the singleton class of the copied object. a_third_baseball = baseball.clone print a_third_baseball.throw # => "THROW" It also maintains the frozen state of the copied object. The clone of a frozen object is also frozen. baseball.freeze print baseball.frozen? # => true a_third_baseball.freeze print a_third_baseball.frozen? # => true another_baseball.freeze print another_baseball.frozen? # => false If we go back to my first example (with Kyrie), we ran into a problem when we noticed that edits made to the copy also changed the original version. There is a way around that, albeit a somewhat hacky way. Instead of: `person_copy = person` ...we will try: person_copy = Marshal.load(Marshal.dump(person)) person_copy[:occupation] = "trapeze artist" # person_copy is now: {:name=>"Kyrie", :occupation=>"trapeze artist"} # person, however, is still: {:name=>"Kyrie", :occupation=>"baller"} Marshalling is a way of making deep copies in Ruby. Deep copies allow the original and the copy to be disconnected. `person_copy` can be modified at no risk to `person`. The variable referencing the copy (`person_Copy`) receives its own local copy of the object. Another quick example of how `dup` and `clone` merely create shallow copies. class Weather attr_accessor :temperature def initialize self.temperature = [65, 61, 57] end end weather = Weather.new print weather.temperature # => [65, 61, 57] more_weather = weather.clone # at this point, more_weather.temperature returns the same thing as weather.temperature print weather.temperature.clear # => [] print more_weather.temperature # => [] Same issue. We modified the original and the copy received the same modification. That's the essence of a shallow copy versus a deep one. *Some Helpful Stuff* [C++ Notes: Shallow vs Deep Copies](http://www.fredosaurus.com/notes-cpp/oop-condestructors/shallowdeepcopy.html) [stackoverflow: What's the differences between ruby dup and clone method?](http://stackoverflow.com/questions/10183370/whats-the-differences-between-ruby-dup-and-clone-method) [Object copy](http://en.wikipedia.org/wiki/Object_copy) [stackoverflow: How to create a deep copy of an object in Ruby?](http://stackoverflow.com/questions/8206523/how-to-create-a-deep-copy-of-an-object-in-ruby) [stackoverflow: What is the difference between a deep copy and a shallow copy?](http://stackoverflow.com/questions/184710/what-is-the-difference-between-a-deep-copy-and-a-shallow-copy)












