[sf-perl] randomize particular lines

Paul Makepeace paul at makepeace.net
Tue Mar 7 03:42:12 PST 2006


Je 2006-03-07 00:50:08 +0000, Quinn Weaver skribis:
>    $word = $words[rand @words]; ## rand returns fractional numbers.
>                                 ## Unfortunately Perl uses floating-point
>                                 ## numbers by default, so it allows
>                                 ## fractional array subscripts.  However,
>                                 ## you can't reliably take the 1.23'th element
>                                 ## of an array.  This expression will
>                                 ## sometimes get you undef, which is
>                                 ## probably not what you want.

This one line is actually quite fine. The $array[rand @array] is a pretty
standard idiom and will do what you want: the rand is rounded down
(i.e. int() is implied) and scalar(@array) is one past the end of the
array so the result is 0..$#array.

>     my @scramble = split(//, $word);
>    @scramble = sort { (-1,1)[rand 2] } @scramble; ## This code cries out for
>                                                   ## documentation.  It
>                                                   ## also suffers from the
>                                                   ## rand problem described
>                                                   ## in my preceding comment.

It's wrong too as sort's behavior doesn't permit a random comparison.

perldoc -f sort,

               The comparison function is required to behave.  If it returns inconsistent results (sometimes saying
               $x[1] is less than $x[2] and sometimes saying the opposite, for example) the results are not
               well-defined.

Which is sort of a shame, as it's cute :-)

Since we're promoting best practices,

  use Algorithm::Numerical::Shuffle 'shuffle';
  @scramble = shuffle(@scramble);

>   $word = $scramble; #if this line omitted, prints the whole file unchanged

(I wonder how $scramble got past the use strict; ?)

> open (DICT, $dictionary) or die "Cannot open $dictionary: $!";
> 
> You could do
> 
>     open my $dict_fh, $dictionary or die "Cannot open $dictionary: $!";
> 
> That way you don't have to worry about whether you already used the
> name DICT, and you can simply pass $dict_fh to other functions.  In
> short, it scales better.  The other use of open isn't incorrect,
> just suboptimal.

Yeah, or

  use File::Slurp 'slurp'; # slurp is preferred Perl 6 name

  my @lines = slurp($dictionary);
  # process @lines
  write_file(\*STDOUT, @lines); # I think this is right

Paul

-- 
Paul Makepeace .............................. http://paulm.com/inchoate/

"If kerry feels horney, then we will put you in our curry."
   -- http://paulm.com/toys/surrealism/


More information about the SanFrancisco-pm mailing list