in reply to Random but non-repeating array loop

Seems perfectly reasonable to me. Here's a similar but shorter construction:

while ($ch = splice(@chars, rand(@chars), 1)) { print "$ch"; }

YuckFoo

Replies are listed 'Best First'.
Re: Re: Random but non-repeating array loop
by blakem (Monsignor) on Jan 19, 2002 at 01:14 UTC
    Nice, but what happens if @chars happens to contain the element '0'? To avoid having the data potentially short-circuit your loop, I might use something like:
    while ($ch = splice(@chars, rand(@chars), 1),@chars) { print "$ch"; }
    Which will exit the loop when @chars is empty, instead of when splice returns FALSE....

    -Blake

      Except that returns false BEFORE @chars is actually empty.
      One element short.
      You should use:
      while (($ch = splice(@chars, rand(@chars), 1))) { print "$ch"; }
      Or wherever you want to place the parentheses.
        Doh! you're absolutely right that my suggestion bails out one element too soon.... However, I don't think your fix changes anything. We need to write the expression so that '0' is TURE but undef and the empty list are FALSE. All of these Deparse the same for me, and all are FALSE-on-0, not TRUE-on-0 as we would like:
        # FALSE-on-0 (bad) % perl -e 'while($x = 0) {sleep print "Hello\n"}' % perl -e 'while(($x = 0)) {sleep print "Hello\n"}' % perl -e 'while((($x = 0))) {sleep print "Hello\n"}' % perl -e 'while(((($x = 0)))) {sleep print "Hello\n"}'
        So, your suggestion of adding those parens around the whole while expression doesn't seem to modify context at all. However, YuckFoo's suggestion will work just fine:
        # TRUE-on-0 (good) % perl -e 'while(($x) = 0 ) {sleep print "Hello\n"}' # but FALSE-on-() (good) % perl -e 'while(($x) = () ) {sleep print "Hello\n"}'
        Which is exactly what we want.

        -Blake

      Doh! Thanks for the pointer. Seems this will also fix '0' data:

      while (($ch) = splice(@chars, rand(@chars), 1)) { print "$ch"; }

      YuckFoo