![]() |
[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 |
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 |
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 |
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 |
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 |
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 |
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. |
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 |
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.