On Thu, 4 Apr 2002 [EMAIL PROTECTED] wrote:
> On Wed, Apr 03, 2002 at 10:37:08PM -0700, Sean M. Burke wrote:
> > I was looking at the implementation of the FY shuffle that I see in
> > Perlfaq4, namely:
> >
> > sub fy1 {
> > my $deck = shift; # $deck is a reference to an array
> > my $i = @$deck;
> > while (--$i) {
> > my $j = int rand ($i+1);
> > @$deck[$i,$j] = @$deck[$j,$i];
> > }
> > }
> >
> > And I thought "guh, that looks a bit off" -- notably, it dies when given an
> > empty array.
It seems I may be to blame for that one... no, wait, the bug was there
even before I touched it. May have been there for as long as that
question has been in perlfaq, for all I know. Still, I should've
noticed the problem and fixed it.
The fix I'd prefer would be to simply add "or return" to the line where
$i is defined. Nice and explicit, and shows a useful idiom too.
> I must say however, that requiring that the array is passed as a
> reference seems an oddity to me. If you pass it a list, it should,
> IMO, return the shuffled list.
The point of taking a reference is that the Fisher-Yates algorithm is an
in-place shuffle. If your array happens to be a couple of megabytes in
size, you start to appreciate this feature. So, since we have this nice
in-place shuffle algorithm, which is just as simple and effective as any
non-in-place alternative could ever be, it seems silly to start making
copies of arrays just to satisfy Perl's return-by-value semantics.
In any case, if you want to shuffle a copy of an array, you can -- just
make the copy before shuffling it. Sure, it's a little extra work, but
it's no worse than what you have to do with s///. Turning an in-place
shuffle into copy-and-shuffle is easy, the other way is impossible.
--
Ilmari Karonen - http://www.sci.fi/~iltzu/
"Signal handlers are known to be broken in perl. Did you expect them to
somehow get unbroken when ITHREADS is enabled?"
-- Gurusamy Sarathy on the perl5-porters list