Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Ruby (http://www.velocityreviews.com/forums/f66-ruby.html)
-   -   [NUBY] Ruby Way code for shuffling an array doesn't behave asexpected (http://www.velocityreviews.com/forums/t815697-nuby-ruby-way-code-for-shuffling-an-array-doesnt-behave-asexpected.html)

Alexey Verkhovsky 07-17-2004 10:12 PM

[NUBY] Ruby Way code for shuffling an array doesn't behave asexpected
 
One example in The Ruby Way claims that in the following snippet second
line shuffles the a (i.e., makes an array consisting of the same
elements as a, but in a different order).

a = [1, 2, 3, 4, 5]
puts a.collect { a.slice!(rand(a.length)) }.inspect

The claim sounds reasonable, but in reality Ruby 1.9 (CVS HEAD) always
returns an array of three random elements, not of five as expected.

Why is that so?

Best regards,
Alexey Verkhovsky




Mark Sparshatt 07-17-2004 10:43 PM

Re: [NUBY] Ruby Way code for shuffling an array doesn't behave asexpected
 
Alexey Verkhovsky wrote:

>One example in The Ruby Way claims that in the following snippet second
>line shuffles the a (i.e., makes an array consisting of the same
>elements as a, but in a different order).
>
>a = [1, 2, 3, 4, 5]
>puts a.collect { a.slice!(rand(a.length)) }.inspect
>
>The claim sounds reasonable, but in reality Ruby 1.9 (CVS HEAD) always
>returns an array of three random elements, not of five as expected.
>
>Why is that so?
>
>
>

This is due to changes in Ruby between v1.6.8 and 1.8

It's because the block passed to collect is changing the contents of a,
so it doesn't reach all the elements of a.

Changing the line to

puts a.dup.collect {a.slice!(rand(a.length)) }.inspect

fixes it

HTH

--
Mark Sparshatt




Mark Hubbart 07-17-2004 10:51 PM

Re: [NUBY] Ruby Way code for shuffling an array doesn't behave as expected
 

On Jul 17, 2004, at 3:12 PM, Alexey Verkhovsky wrote:

> One example in The Ruby Way claims that in the following snippet second
> line shuffles the a (i.e., makes an array consisting of the same
> elements as a, but in a different order).
>
> a = [1, 2, 3, 4, 5]
> puts a.collect { a.slice!(rand(a.length)) }.inspect
>
> The claim sounds reasonable, but in reality Ruby 1.9 (CVS HEAD) always
> returns an array of three random elements, not of five as expected.
>
> Why is that so?


It appears that #each is being affected by the slicing of the array
that it is acting on. By the time it gets to the third element, it's
the last one. So it stops.

It doesn't seem to do that in 1.6.x; I assume #each worked on a copy of
the array back then...

RUBY_VERSION
==>"1.6.8"
a=[1,2,3,4,5]
==>[1, 2, 3, 4, 5]
p a.collect{a.slice!(rand(a.length))}
[4, 3, 5, 2, 1]
==>nil

To fix it in later versions, use a.dup.collect instead. That should fix
the odd behavior.

HTH,
Mark




Alexey Verkhovsky 07-17-2004 11:12 PM

Re: [NUBY] Ruby Way code for shuffling an array doesn't behave asexpected
 
On Sun, 2004-07-18 at 01:43, Mark Sparshatt wrote:
> It's because the block passed to collect is changing the contents of a,
> so it doesn't reach all the elements of a.


So, Ruby iterators operate on the original collection and let you modify
the collection in the process. Another fact useful to remember.

This is, by the way, one thing I like about Java iterators: they are
fail-safe in such scenarios. E.g.

List list = new ArrayList(2);
list.add(new Object());
list.add(new Object());
Iterator i = list.iterator();
i.next(); // this is OK
list.add(new Object()); // list gets changed
i.next(); // throws ConcurrentModificationException

IMHO, an exception here is The Right Thing (TM). At least, it saved me
from my own stupid mistakes more than once.

Best regards,
Alex








Mark Hubbart 07-18-2004 12:04 AM

Re: [NUBY] Ruby Way code for shuffling an array doesn't behave as expected
 

On Jul 17, 2004, at 4:12 PM, Alexey Verkhovsky wrote:

> On Sun, 2004-07-18 at 01:43, Mark Sparshatt wrote:
>> It's because the block passed to collect is changing the contents of
>> a,
>> so it doesn't reach all the elements of a.

>
> So, Ruby iterators operate on the original collection and let you
> modify
> the collection in the process. Another fact useful to remember.
>
> This is, by the way, one thing I like about Java iterators: they are
> fail-safe in such scenarios. E.g.
>
> List list = new ArrayList(2);
> list.add(new Object());
> list.add(new Object());
> Iterator i = list.iterator();
> i.next(); // this is OK
> list.add(new Object()); // list gets changed
> i.next(); // throws ConcurrentModificationException
>
> IMHO, an exception here is The Right Thing (TM). At least, it saved me
> from my own stupid mistakes more than once.


I'm not sure that an exception would be The Right Thing, but I do
wonder why it no longer works on a copy of the array? Allowing
modification of the actual array as you iterate over it seems
dangerous.

But there must have been a reason for abandoning the original
behavior... Perhaps it was a performance issue?

cheers,
Mark




Alexey Verkhovsky 07-18-2004 12:43 AM

Re: [NUBY] Ruby Way code for shuffling an array doesn't behave asexpected
 
On Sun, 2004-07-18 at 03:04, Mark Hubbart wrote:
> I'm not sure that an exception would be The Right Thing

A smilie was inadvertently omitted in my earlier post. It should have
said "The Right Thing (TM) :)"

:)

Life is full of compromises, and on the issue of what to do with stale
iterators, there are at least three choices:

1. Nothing (fast and dangerous)
2. Iterate over a copy (safe and slow)
3. Iterate over the original, but detect stale iterators (the middle
way, much safer than 1 and somewhat faster than 2).

Each of the three choices has pros and cons.

All I'm saying is that in my personal experience Java's
ConcurrentModificationException has prevented or exposed many bugs that
otherwise would be subtle and probably very costly affairs. Which is why
I like it.

But then, the most important difference between Ruby and Java is that
the former lets you do anything, and that includes shooting yourself in
the foot, too. The latter, meantime, does not believe that you REALLY
know what you are doing. :)

Best regards,
Alex





Gully Foyle 07-18-2004 12:52 AM

Re: [NUBY] Ruby Way code for shuffling an array doesn't behave asexpected
 
Alexey Verkhovsky wrote:
> On Sun, 2004-07-18 at 03:04, Mark Hubbart wrote:
>
>>I'm not sure that an exception would be The Right Thing

>
> A smilie was inadvertently omitted in my earlier post. It should have
> said "The Right Thing (TM) :)"
>
> :)
>
> Life is full of compromises, and on the issue of what to do with stale
> iterators, there are at least three choices:
>
> 1. Nothing (fast and dangerous)
> 2. Iterate over a copy (safe and slow)
> 3. Iterate over the original, but detect stale iterators (the middle
> way, much safer than 1 and somewhat faster than 2).
>
> Each of the three choices has pros and cons.
>
> All I'm saying is that in my personal experience Java's
> ConcurrentModificationException has prevented or exposed many bugs that
> otherwise would be subtle and probably very costly affairs. Which is why
> I like it.
>
> But then, the most important difference between Ruby and Java is that
> the former lets you do anything, and that includes shooting yourself in
> the foot, too. The latter, meantime, does not believe that you REALLY
> know what you are doing. :)
>
> Best regards,
> Alex
>
>
>
>


One alternative solution is to provide for all three options using a
resettable flag. Kinda like $SAFE for security.

Florian Gross 07-18-2004 10:13 AM

Re: [NUBY] Ruby Way code for shuffling an array doesn't behave asexpected
 
Alexey Verkhovsky wrote:

> One example in The Ruby Way claims that in the following snippet second
> line shuffles the a (i.e., makes an array consisting of the same
> elements as a, but in a different order).


By the way, if you just want to shuffle an Array you can also use the
much simpler ary.sort_by { rand }. (It will get minimally biased with
containers containing millions of elements, but that can be fixed by
using Array.new(32) { rand } instead of rand.)

> Best regards,
> Alexey Verkhovsky


More regards,
Florian Gross

Hal Fulton 07-18-2004 01:57 PM

Re: [NUBY] Ruby Way code for shuffling an array doesn't behave asexpected
 
Florian Gross wrote:
> Alexey Verkhovsky wrote:
>
>> One example in The Ruby Way claims that in the following snippet second
>> line shuffles the a (i.e., makes an array consisting of the same
>> elements as a, but in a different order).

>
>
> By the way, if you just want to shuffle an Array you can also use the
> much simpler ary.sort_by { rand }. (It will get minimally biased with
> containers containing millions of elements, but that can be fixed by
> using Array.new(32) { rand } instead of rand.)


And by the way, the code which modified the array while iterating
was probably ill-advised from the beginning, although it did work
in 1.6.8.


Hal





All times are GMT. The time now is 02:40 PM.

Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57