PLEASE HELP...dup is not working correctly in the following code

Discussion in 'Ruby' started by timr, Dec 29, 2009.

  1. timr

    timr Guest

    #dup creates a copy of an object with a different object_id. As
    follows:
    => [1, 2, 3, 1000]

    Changing b does't change a because b is a copy of a with a different
    object_id.

    However, unlike the irb session, the following code shows that
    modification of the dupped object is somehow changing the original.
    WTF? (you may want to change the font to courier to get the maze to
    line up correctly). This behavior is so strange. I can see no
    significant differences between the usage in the irb session and in
    this code, yet the behavior is very different. Please explain if you
    have any insights.
    Thanks,
    Tim

    @maze1 = %{#####################################
    # # # #A # # #
    # # # # # # ####### # ### # ####### #
    # # # # # # # # #
    # ##### # ################# # #######
    # # # # # # # # #
    ##### ##### ### ### # ### # # # # # #
    # # # # # # B# # # # # #
    # # ##### ##### # # ### # # ####### #
    # # # # # # # # # # # #
    # ### ### # # # # ##### # # # ##### #
    # # # # # # #
    #####################################}
    class Maze
    attr_accessor :maze

    #initialize creates a @maze array with each row a sub array
    def initialize(maze_name)
    @maze = maze_name.split(/\n/).collect{|row| row.split(//)}
    @maze_dup = @maze.dup
    end
    def write_(r, c)
    @maze_dup[r][c] = "a"
    end
    def report
    puts "@maze:"
    @maze.each{|r| p r.join}
    puts "@maze_dup:"
    @maze_dup.each{|r| p r.join}
    end
    end

    maze1 = Maze.new(@maze1)
    maze1.report
    maze1.write_(0,0)
    maze1.report
    maze1.write_(1,1)
    maze1.report


    # >> @maze:
    # >> "#####################################"
    # >> "# # # #A # # #"
    # >> "# # # # # # ####### # ### # ####### #"
    # >> "# # # # # # # # #"
    # >> "# ##### # ################# # #######"
    # >> "# # # # # # # # #"
    # >> "##### ##### ### ### # ### # # # # # #"
    # >> "# # # # # # B# # # # # #"
    # >> "# # ##### ##### # # ### # # ####### #"
    # >> "# # # # # # # # # # # #"
    # >> "# ### ### # # # # ##### # # # ##### #"
    # >> "# # # # # # #"
    # >> "#####################################"
    # >> @maze_dup:
    # >> "#####################################"
    # >> "# # # #A # # #"
    # >> "# # # # # # ####### # ### # ####### #"
    # >> "# # # # # # # # #"
    # >> "# ##### # ################# # #######"
    # >> "# # # # # # # # #"
    # >> "##### ##### ### ### # ### # # # # # #"
    # >> "# # # # # # B# # # # # #"
    # >> "# # ##### ##### # # ### # # ####### #"
    # >> "# # # # # # # # # # # #"
    # >> "# ### ### # # # # ##### # # # ##### #"
    # >> "# # # # # # #"
    # >> "#####################################"
    # >> @maze:
    # >> "a####################################"
    # >> "# # # #A # # #"
    # >> "# # # # # # ####### # ### # ####### #"
    # >> "# # # # # # # # #"
    # >> "# ##### # ################# # #######"
    # >> "# # # # # # # # #"
    # >> "##### ##### ### ### # ### # # # # # #"
    # >> "# # # # # # B# # # # # #"
    # >> "# # ##### ##### # # ### # # ####### #"
    # >> "# # # # # # # # # # # #"
    # >> "# ### ### # # # # ##### # # # ##### #"
    # >> "# # # # # # #"
    # >> "#####################################"
    # >> @maze_dup:
    # >> "a####################################"
    # >> "# # # #A # # #"
    # >> "# # # # # # ####### # ### # ####### #"
    # >> "# # # # # # # # #"
    # >> "# ##### # ################# # #######"
    # >> "# # # # # # # # #"
    # >> "##### ##### ### ### # ### # # # # # #"
    # >> "# # # # # # B# # # # # #"
    # >> "# # ##### ##### # # ### # # ####### #"
    # >> "# # # # # # # # # # # #"
    # >> "# ### ### # # # # ##### # # # ##### #"
    # >> "# # # # # # #"
    # >> "#####################################"
    # >> @maze:
    # >> "a####################################"
    # >> "#a# # #A # # #"
    # >> "# # # # # # ####### # ### # ####### #"
    # >> "# # # # # # # # #"
    # >> "# ##### # ################# # #######"
    # >> "# # # # # # # # #"
    # >> "##### ##### ### ### # ### # # # # # #"
    # >> "# # # # # # B# # # # # #"
    # >> "# # ##### ##### # # ### # # ####### #"
    # >> "# # # # # # # # # # # #"
    # >> "# ### ### # # # # ##### # # # ##### #"
    # >> "# # # # # # #"
    # >> "#####################################"
    # >> @maze_dup:
    # >> "a####################################"
    # >> "#a# # #A # # #"
    # >> "# # # # # # ####### # ### # ####### #"
    # >> "# # # # # # # # #"
    # >> "# ##### # ################# # #######"
    # >> "# # # # # # # # #"
    # >> "##### ##### ### ### # ### # # # # # #"
    # >> "# # # # # # B# # # # # #"
    # >> "# # ##### ##### # # ### # # ####### #"
    # >> "# # # # # # # # # # # #"
    # >> "# ### ### # # # # ##### # # # ##### #"
    # >> "# # # # # # #"
    # >> "#####################################"
     
    timr, Dec 29, 2009
    #1
    1. Advertisements

  2. timr

    Seebs Guest

    No, it isn't.

    You have two separate arrays.

    However, each of those arrays contains the same strings -- the first string
    of each array is the same object.

    You want a deep copy (where you duplicate all the objects in the array,
    not just the arrays). Something like:

    @maze_dup = @maze.map { |x| x.dup }

    .... I think.

    -s
     
    Seebs, Dec 29, 2009
    #2
    1. Advertisements

  3. timr

    timr Guest

    You are right about the strings having the same object_ids in each
    object, which explains why the modification on the dupped object
    affects the original strings. That helps. But the suggested strategy
    doesn't solve the problem:
    4442750
    4442740
    4442710
    4442700
    => [["a", "b"], ["c", "d"]]
    4442750
    4442740
    4442710
    4442700

    Still the same object_ids for all of the contents.
    Tim
     
    timr, Dec 29, 2009
    #3
  4. timr

    Seebs Guest

    This doesn't seem right. The inner loop (which is the one I think
    we care about) is using each, not map. So we never actually return
    the array consisting of all the duplicated letters.

    If you have an array of arrays, I think you need to use map at both
    levels.

    irb(main):001:0> a = [['a', 'b'], ['c','d']]
    => [["a", "b"], ["c", "d"]]
    irb(main):002:0> b = a.map {|r| r.map{|l| l.dup}}
    => [["a", "b"], ["c", "d"]]
    irb(main):003:0> a.each{|r| r.each{|letter| p letter.object_id}}
    2152912244
    2152912216
    2152912132
    2152912104
    => [["a", "b"], ["c", "d"]]
    irb(main):004:0> b.each{|r| r.each{|letter| p letter.object_id}}
    2152886456
    2152886316
    2152886232
    2152886176
    => [["a", "b"], ["c", "d"]]

    What's throwing you off here is that .each returns the array object
    it started with.

    So "r.each {...}" always returns r, unmodified.

    -s
     
    Seebs, Dec 29, 2009
    #4
  5. timr

    Josh Cheek Guest

    [Note: parts of this message were removed to make it a legal post.]

    This is the difference

    $ irb
    => ["w", "x", "y"]
    => ["w", "x", "y"]
    => ["w", "x", "y", "z"]
    => ["w", "x", "y"]
    => "wx"
    => ["wx", "x", "y", "z"]
    => ["wx", "x", "y"]


    a and b are different arrays, but they each contain the same objects.

    I think the only way to make a deep copy is to explicitly dup everything in
    the array also, or to use marshall. I'm not sure why there isn't a deep copy
    method.
     
    Josh Cheek, Dec 29, 2009
    #5
  6. irb(main):001:0> array = ["string"]
    => ["string"]
    irb(main):002:0> array_dup = []
    => []
    irb(main):003:0> array_dup[0] = array[0].clone
    => "string"
    irb(main):004:0> array_dup[0].object_id
    => 30816948
    irb(main):005:0> array[0].object_id
    => 30838824
     
    Phillip Gawlowski, Dec 29, 2009
    #6
  7. timr

    timr Guest

    I was just going to post that correction after I realized that
    mistake. Thanks for the help.
     
    timr, Dec 29, 2009
    #7
  8. #dup creates a copy of an object with a different object_id. As
    =3D> 2157328320

    Regards,
    Rimantas
     
    Rimantas Liubertas, Dec 29, 2009
    #8
  9. timr

    Seebs Guest

    Thanks for asking the question with enough detail, and illustrations,
    that it was *possible* to help.

    -s
     
    Seebs, Dec 29, 2009
    #9
  10. timr

    timr Guest

    This is in effect the deep copy of a complex array containing strings
    that we were pining for. I think it is easier to do it this ways than
    to map through all of the nested arrays. Thanks for the irb demo of
    its use.
     
    timr, Dec 29, 2009
    #10
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.