suprised by destructive map (not map!)

Discussion in 'Ruby' started by Boris Schmid, Dec 13, 2007.

  1. Boris Schmid

    Boris Schmid Guest

    Occasionally I run into bits of ruby that are surprising to me (although
    might not be to matz). Here is one of them. Should I file this as a bug
    (I thought .map is supposed to be non-destructive), or just keep in mind
    which classes are passed by value and which are passed by reference.

    Basically: map (and naturally also map!) is destructive when your array
    includes elements which are normally not passed by value but by
    reference.

    ruby 1.8.6 (2007-09-24 patchlevel 111) [x86_64-linux]
    boris:falcon:~:irb

    "unexpected (for me)"
    irb(main):001:0> array = [[1],[2]]
    => [[1], [2]]
    irb(main):002:0> array.map {|i| i << 3}
    => [[1, 3], [2, 3]]
    irb(main):003:0> array
    => [[1, 3], [2, 3]]
    irb(main):004:0>

    "expected behaviour"
    irb(main):005:0* array = [1,2]
    => [1, 2]
    irb(main):006:0> array.map {|i| i + 3}
    => [4, 5]
    irb(main):007:0> array
    => [1, 2]
    irb(main):008:0>
    --
    Posted via http://www.ruby-forum.com/.
    Boris Schmid, Dec 13, 2007
    #1
    1. Advertising

  2. Boris Schmid

    Alex Young Guest

    Boris Schmid wrote:
    > Occasionally I run into bits of ruby that are surprising to me (although
    > might not be to matz). Here is one of them. Should I file this as a bug
    > (I thought .map is supposed to be non-destructive), or just keep in mind
    > which classes are passed by value and which are passed by reference.
    >
    > Basically: map (and naturally also map!) is destructive when your array
    > includes elements which are normally not passed by value but by
    > reference.
    >
    > ruby 1.8.6 (2007-09-24 patchlevel 111) [x86_64-linux]
    > boris:falcon:~:irb
    >
    > "unexpected (for me)"
    > irb(main):001:0> array = [[1],[2]]
    > => [[1], [2]]
    > irb(main):002:0> array.map {|i| i << 3}
    > => [[1, 3], [2, 3]]
    > irb(main):003:0> array
    > => [[1, 3], [2, 3]]
    > irb(main):004:0>


    It's not map that's destructive here, it's the #<< method. Map iterates
    over the original array, and creates a new one with the results of the
    block - it doesn't copy the original array first.

    --
    Alex
    Alex Young, Dec 13, 2007
    #2
    1. Advertising

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

    Use it:
    irb(main):001:0> array = [[1], [2]]
    => [[1], [2]]
    irb(main):002:0> array.map{|a| a += [3]}
    => [[1, 3], [2, 3]]
    irb(main):003:0> array
    => [[1], [2]]

    --
    Bernardo Rufino
    Bernardo Monteiro Rufino, Dec 13, 2007
    #3
  4. Boris Schmid

    Alex Young Guest

    Bernardo Monteiro Rufino wrote:
    > Use it:
    > irb(main):001:0> array = [[1], [2]]
    > => [[1], [2]]
    > irb(main):002:0> array.map{|a| a += [3]}


    That expands to:

    array.map{|a| a = a + [3] }

    The Array#+ method isn't destructive, and a variable assignment in a
    block isn't either.

    --
    Alex
    Alex Young, Dec 13, 2007
    #4
  5. [Note: parts of this message were removed to make it a legal post.]

    Exactly

    --
    Bernardo Rufino
    Bernardo Monteiro Rufino, Dec 13, 2007
    #5
  6. Boris Schmid

    Boris Schmid Guest

    Thanks for clarifying that. I'll compile a list of destructive methods
    for myself, and be aware of them when I map.

    Also learned not to trust blindly in the ! from another post.
    --
    Posted via http://www.ruby-forum.com/.
    Boris Schmid, Dec 13, 2007
    #6
  7. 2007/12/13, Boris Schmid <>:
    > Thanks for clarifying that. I'll compile a list of destructive methods
    > for myself, and be aware of them when I map.
    >
    > Also learned not to trust blindly in the ! from another post.


    You should also remember that all parameters are passed by reference*.
    Whether hazard occurs depends on what you do with them, especially
    the mutable ones. In your case elements in your Array were Arrays
    which are mutable. The issue does not happen if you used integers
    instead - even with <<:

    irb(main):001:0> a1 = [1,2]
    => [1, 2]
    irb(main):002:0> a2 = a1.map {|x| x << 1}
    => [2, 4]
    irb(main):003:0> a1
    => [1, 2]

    * Note: this is not 100% correct implementation wise but describes the
    situation properly from a Ruby user's point of view.

    Kind regards

    robert

    --
    use.inject do |as, often| as.you_can - without end
    Robert Klemme, Dec 14, 2007
    #7
  8. Boris Schmid

    tho_mica_l Guest

    > irb(main):002:0> array.map {|i| i << 3}
    > => [[1, 3], [2, 3]]


    Well, Array#<< means: __append__ an element to an array and return
    the
    array. It does not mean make a copy of the array plus the new
    element.
    What you expected would be one of

    array.map {|i| i.dup << 3}
    array.map {|i| i + [3]}

    It's not necessary to use += here since the value of "i += [3]" is i,
    which you really don't care about since you only want "i + [3]".

    Fixnum#<< means shift bits. Same symbol but totally different story.
    Also, numerics are no container classes but have immediate values,
    i.e.
    they are not passed by reference (according to Programming Ruby 2,
    p463), which is also why you can't dup/clone them.
    tho_mica_l, Dec 14, 2007
    #8
  9. > array.map{|a| a += [3]}
    >
    > That expands to:
    >
    > array.map{|a| a = a + [3] }


    You might want to skip the useless assignment:

    array.map{|a| a + [3]}

    gegroet,
    Erik V. - http://www.erikveen.dds.nl/
    Erik Veenstra, Dec 14, 2007
    #9
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ville Vainio
    Replies:
    11
    Views:
    470
    Ville Vainio
    Apr 6, 2005
  2. rbt

    Destructive Windows Script

    rbt, Jun 6, 2005, in forum: Python
    Replies:
    27
    Views:
    665
    John J. Lee
    Jun 10, 2005
  3. Mad Programmer
    Replies:
    18
    Views:
    796
    Jim Langston
    Sep 13, 2005
  4. Daniel Pitts

    Re: Non destructive read of socket

    Daniel Pitts, Oct 6, 2009, in forum: Java
    Replies:
    1
    Views:
    398
    Tom Anderson
    Oct 7, 2009
  5. EJP
    Replies:
    9
    Views:
    445
Loading...

Share This Page