Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > suprised by destructive map (not map!)

Reply
Thread Tools

suprised by destructive map (not map!)

 
 
Boris Schmid
Guest
Posts: n/a
 
      12-13-2007
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/.

 
Reply With Quote
 
 
 
 
Alex Young
Guest
Posts: n/a
 
      12-13-2007
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

 
Reply With Quote
 
 
 
 
Bernardo Monteiro Rufino
Guest
Posts: n/a
 
      12-13-2007
[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

 
Reply With Quote
 
Alex Young
Guest
Posts: n/a
 
      12-13-2007
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



 
Reply With Quote
 
Bernardo Monteiro Rufino
Guest
Posts: n/a
 
      12-13-2007
[Note: parts of this message were removed to make it a legal post.]

Exactly

--
Bernardo Rufino

 
Reply With Quote
 
Boris Schmid
Guest
Posts: n/a
 
      12-13-2007
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/.

 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      12-14-2007
2007/12/13, Boris Schmid <(E-Mail Removed)>:
> 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

 
Reply With Quote
 
tho_mica_l
Guest
Posts: n/a
 
      12-14-2007
> 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.
 
Reply With Quote
 
Erik Veenstra
Guest
Posts: n/a
 
      12-14-2007
> 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/

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
NTFS data recovery after non-destructive restore Ike Milligan Computer Support 1 06-05-2006 11:58 PM
Which Non Destructive Glue to Use on Mats Mike Digital Photography 12 02-27-2006 02:48 AM
Writing a destructive trojan with C++... Mad Programmer C++ 18 09-13-2005 10:14 PM
Destructive Windows Script rbt Python 27 06-10-2005 06:26 PM
Case-insensitive dict, non-destructive, fast, anyone? Ville Vainio Python 11 04-06-2005 06:53 AM



Advertisments