Force RVALUE macros when in PERL_DEBUG_COW
[p5sagit/p5-mst-13.2.git] / pod / perlfaq4.pod
index 7c616ac..de7feee 100644 (file)
@@ -1,6 +1,6 @@
 =head1 NAME
 
-perlfaq4 - Data Manipulation ($Revision: 1.37 $, $Date: 2002/11/13 06:04:00 $)
+perlfaq4 - Data Manipulation ($Revision: 1.61 $, $Date: 2005/03/11 16:27:53 $)
 
 =head1 DESCRIPTION
 
@@ -22,12 +22,30 @@ representations and conversions.
 
 To limit the number of decimal places in your numbers, you
 can use the printf or sprintf function.  See the
-L<perlop|"Floating Point Arithmetic"> for more details.
+L<"Floating Point Arithmetic"|perlop> for more details.
 
        printf "%.2f", 10/3;
-       
+
        my $number = sprintf "%.2f", 10/3;
-       
+
+=head2 Why is int() broken?
+
+Your int() is most probably working just fine.  It's the numbers that
+aren't quite what you think.
+
+First, see the above item "Why am I getting long decimals
+(eg, 19.9499999999999) instead of the numbers I should be getting
+(eg, 19.95)?".
+
+For example, this
+
+    print int(0.6/0.2-2), "\n";
+
+will in most computers print 0, not 1, because even such simple
+numbers as 0.6 and 0.2 cannot be presented exactly by floating-point
+numbers.  What you think in the above as 'three' is really more like
+2.9999999999999995559.
+
 =head2 Why isn't my octal data interpreted correctly?
 
 Perl only understands octal and hex numbers as such when they occur as
@@ -43,13 +61,13 @@ The inverse mapping from decimal to octal can be done with either the
 "%o" or "%O" sprintf() formats.
 
 This problem shows up most often when people try using chmod(), mkdir(),
-umask(), or sysopen(), which by widespread tradition typically take 
+umask(), or sysopen(), which by widespread tradition typically take
 permissions in octal.
 
     chmod(644,  $file);        # WRONG
     chmod(0644, $file);        # right
 
-Note the mistake in the first line was specifying the decimal literal 
+Note the mistake in the first line was specifying the decimal literal
 644, rather than the intended octal literal 0644.  The problem can
 be seen with:
 
@@ -57,7 +75,7 @@ be seen with:
 
 Surely you had not intended C<chmod(01204, $file);> - did you?  If you
 want to use numeric literals as arguments to chmod() et al. then please
-try to express them as octal constants, that is with a leading zero and 
+try to express them as octal constants, that is with a leading zero and
 with the following digits restricted to the set 0..7.
 
 =head2 Does Perl have a round() function?  What about ceil() and floor()?  Trig functions?
@@ -94,7 +112,7 @@ alternation:
 
     for ($i = 0; $i < 1.01; $i += 0.05) { printf "%.1f ",$i}
 
-    0.0 0.1 0.1 0.2 0.2 0.2 0.3 0.3 0.4 0.4 0.5 0.5 0.6 0.7 0.7 
+    0.0 0.1 0.1 0.2 0.2 0.2 0.3 0.3 0.4 0.4 0.5 0.5 0.6 0.7 0.7
     0.8 0.8 0.9 0.9 1.0 1.0
 
 Don't blame Perl.  It's the same as in C.  IEEE says we have to do this.
@@ -102,7 +120,7 @@ Perl numbers whose absolute values are integers under 2**31 (on 32 bit
 machines) will work pretty much like mathematical integers.  Other numbers
 are not guaranteed.
 
-=head2 How do I convert between numeric representations?
+=head2 How do I convert between numeric representations/bases/radixes?
 
 As always with Perl there is more than one way to do it.  Below
 are a few examples of approaches to making common conversions
@@ -121,18 +139,15 @@ programmers the notation might be familiar.
 
 Using perl's built in conversion of 0x notation:
 
-    $int = 0xDEADBEEF;
-    $dec = sprintf("%d", $int);
+    $dec = 0xDEADBEEF;
 
 Using the hex function:
 
-    $int = hex("DEADBEEF");
-    $dec = sprintf("%d", $int);
+    $dec = hex("DEADBEEF");
 
 Using pack:
 
-    $int = unpack("N", pack("H8", substr("0" x 8 . "DEADBEEF", -8)));
-    $dec = sprintf("%d", $int);
+    $dec = unpack("N", pack("H8", substr("0" x 8 . "DEADBEEF", -8)));
 
 Using the CPAN module Bit::Vector:
 
@@ -142,15 +157,16 @@ Using the CPAN module Bit::Vector:
 
 =item How do I convert from decimal to hexadecimal
 
-Using sprint:
+Using sprintf:
 
-    $hex = sprintf("%X", 3735928559);
+    $hex = sprintf("%X", 3735928559); # upper case A-F
+    $hex = sprintf("%x", 3735928559); # lower case a-f
 
-Using unpack
+Using unpack:
 
     $hex = unpack("H*", pack("N", 3735928559));
 
-Using Bit::Vector
+Using Bit::Vector:
 
     use Bit::Vector;
     $vec = Bit::Vector->new_Dec(32, -559038737);
@@ -167,13 +183,11 @@ And Bit::Vector supports odd bit counts:
 
 Using Perl's built in conversion of numbers with leading zeros:
 
-    $int = 033653337357; # note the leading 0!
-    $dec = sprintf("%d", $int);
+    $dec = 033653337357; # note the leading 0!
 
 Using the oct function:
 
-    $int = oct("33653337357");
-    $dec = sprintf("%d", $int);
+    $dec = oct("33653337357");
 
 Using Bit::Vector:
 
@@ -188,7 +202,7 @@ Using sprintf:
 
     $oct = sprintf("%o", 3735928559);
 
-Using Bit::Vector
+Using Bit::Vector:
 
     use Bit::Vector;
     $vec = Bit::Vector->new_Dec(32, -559038737);
@@ -199,13 +213,18 @@ Using Bit::Vector
 Perl 5.6 lets you write binary numbers directly with
 the 0b notation:
 
-       $number = 0b10110110;
+    $number = 0b10110110;
+
+Using oct:
+
+    my $input = "10110110";
+    $decimal = oct( "0b$input" );
 
-Using pack and ord
+Using pack and ord:
 
     $decimal = ord(pack('B8', '10110110'));
 
-Using pack and unpack for larger strings
+Using pack and unpack for larger strings:
 
     $int = unpack("N", pack("B32",
        substr("0" x 32 . "11110101011011011111011101111", -32)));
@@ -220,7 +239,11 @@ Using Bit::Vector:
 
 =item How do I convert from decimal to binary
 
-Using unpack;
+Using sprintf (perl 5.6+):
+
+    $bin = sprintf("%b", 3735928559);
+
+Using unpack:
 
     $bin = unpack("B*", pack("N", 3735928559));
 
@@ -316,7 +339,7 @@ Get the http://www.cpan.org/modules/by-module/Roman module.
 If you're using a version of Perl before 5.004, you must call C<srand>
 once at the start of your program to seed the random number generator.
 
-        BEGIN { srand() if $[ < 5.004 }
+        BEGIN { srand() if $] < 5.004 }
 
 5.004 and later automatically call C<srand> at the beginning.  Don't
 call C<srand> more than once---you make your numbers less random, rather
@@ -339,9 +362,20 @@ pseudorandom generator than comes with your operating system, look at
 
 =head2 How do I get a random number between X and Y?
 
-Use the following simple function.  It selects a random integer between
-(and possibly including!) the two given integers, e.g.,
-C<random_int_in(50,120)>
+C<rand($x)> returns a number such that
+C<< 0 <= rand($x) < $x >>. Thus what you want to have perl
+figure out is a random number in the range from 0 to the
+difference between your I<X> and I<Y>.
+
+That is, to get a number between 10 and 15, inclusive, you
+want a random number between 0 and 5 that you can then add
+to 10.
+
+    my $number = 10 + int rand( 15-10+1 );
+
+Hence you derive the following simple function to abstract
+that. It selects a random integer between the two given
+integers (inclusive), For example: C<random_int_in(50,120)>.
 
    sub random_int_in ($$) {
      my($min, $max) = @_;
@@ -353,31 +387,45 @@ C<random_int_in(50,120)>
 
 =head1 Data: Dates
 
-=head2 How do I find the week-of-the-year/day-of-the-year?
+=head2 How do I find the day or week of the year?
+
+The localtime function returns the day of the year.  Without an
+argument localtime uses the current time.
+
+    $day_of_year = (localtime)[7];
+
+The POSIX module can also format a date as the day of the year or
+week of the year.
+
+       use POSIX qw/strftime/;
+       my $day_of_year  = strftime "%j", localtime;
+       my $week_of_year = strftime "%W", localtime;
+
+To get the day of year for any date, use the Time::Local module to get
+a time in epoch seconds for the argument to localtime.
 
-The day of the year is in the array returned by localtime() (see
-L<perlfunc/"localtime">):
+       use POSIX qw/strftime/;
+       use Time::Local;
+       my $week_of_year = strftime "%W", 
+               localtime( timelocal( 0, 0, 0, 18, 11, 1987 ) );
 
-    $day_of_year = (localtime(time()))[7];
+The Date::Calc module provides two functions for to calculate these.
+
+       use Date::Calc;
+       my $day_of_year  = Day_of_Year(  1987, 12, 18 );
+       my $week_of_year = Week_of_Year( 1987, 12, 18 );
 
 =head2 How do I find the current century or millennium?
 
 Use the following simple functions:
 
-    sub get_century    { 
+    sub get_century    {
        return int((((localtime(shift || time))[5] + 1999))/100);
-    } 
-    sub get_millennium { 
+    }
+    
+    sub get_millennium {
        return 1+int((((localtime(shift || time))[5] + 1899))/1000);
-    } 
-
-You can also use the POSIX strftime() function which may be a bit
-slower but is easier to read and maintain.
-
-       use POSIX qw/strftime/;
-       
-       my $week_of_the_year = strftime "%W", localtime;
-       my $day_of_the_year  = strftime "%j", localtime;
+    }
 
 On some systems, the POSIX module's strftime() function has
 been extended in a non-standard way to use a C<%C> format,
@@ -407,26 +455,29 @@ and Date::Manip modules from CPAN.
 
 =head2 How can I find the Julian Day?
 
-Use the Time::JulianDay module (part of the Time-modules bundle
-available from CPAN.)
-
-Before you immerse yourself too deeply in this, be sure to verify that
-it is the I<Julian> Day you really want.  Are you interested in a way
-of getting serial days so that you just can tell how many days they
-are apart or so that you can do also other date arithmetic?  If you
-are interested in performing date arithmetic, this can be done using
-modules Date::Manip or Date::Calc.
-
-There is too many details and much confusion on this issue to cover in
-this FAQ, but the term is applied (correctly) to a calendar now
-supplanted by the Gregorian Calendar, with the Julian Calendar failing
-to adjust properly for leap years on centennial years (among other
-annoyances).  The term is also used (incorrectly) to mean: [1] days in
-the Gregorian Calendar; and [2] days since a particular starting time
-or `epoch', usually 1970 in the Unix world and 1980 in the
-MS-DOS/Windows world.  If you find that it is not the first meaning
-that you really want, then check out the Date::Manip and Date::Calc
-modules.  (Thanks to David Cassell for most of this text.)
+(contributed by brian d foy and Dave Cross)
+
+You can use the Time::JulianDay module available on CPAN.  Ensure that
+you really want to find a Julian day, though, as many people have
+different ideas about Julian days.  See
+http://www.hermetic.ch/cal_stud/jdn.htm for instance.
+
+You can also try the DateTime module, which can convert a date/time
+to a Julian Day.
+
+  $ perl -MDateTime -le'print DateTime->today->jd'
+  2453401.5
+
+Or the modified Julian Day
+
+  $ perl -MDateTime -le'print DateTime->today->mjd'
+  53401
+
+Or even the day of the year (which is what some people think of as a
+Julian day)
+
+  $ perl -MDateTime -le'print DateTime->today->doy'
+  31
 
 =head2 How do I find yesterday's date?
 
@@ -434,9 +485,9 @@ If you only need to find the date (and not the same time), you
 can use the Date::Calc module.
 
        use Date::Calc qw(Today Add_Delta_Days);
-       
+
        my @date = Add_Delta_Days( Today(), -1 );
-       
+
        print "@date\n";
 
 Most people try to use the time rather than the calendar to
@@ -452,7 +503,7 @@ throws this off. Russ Allbery offers this solution.
                my $tdst = (localtime $then)[8] > 0;
                $then - ($tdst - $ndst) * 60 * 60;
                }
-               
+
 Should give you "this time yesterday" in seconds since epoch relative to
 the first argument or the current time if no argument is given and
 suitable for passing to localtime or whatever else you need to do with
@@ -512,7 +563,7 @@ C<$timestamp = gmtime(1005613200)> sets $timestamp to "Tue Nov 13 01:00:00
 That doesn't mean that Perl can't be used to create non-Y2K compliant
 programs.  It can.  But so can your pencil.  It's the fault of the user,
 not the language.  At the risk of inflaming the NRA: ``Perl doesn't
-break Y2K, people do.''  See http://language.perl.com/news/y2k.html for
+break Y2K, people do.''  See http://www.perl.org/about/y2k.html for
 a longer exposition.
 
 =head1 Data: Strings
@@ -551,9 +602,6 @@ a subroutine call (in list context) into a string:
 
     print "My sub returned @{[mysub(1,2,3)]} that time.\n";
 
-See also ``How can I expand variables in text strings?'' in this
-section of the FAQ.
-
 =head2 How do I find matching/nesting anything?
 
 This isn't something that can be done in one regular expression, no
@@ -576,7 +624,7 @@ pull out the smallest nesting parts one at a time:
 
     while (s/BEGIN((?:(?!BEGIN)(?!END).)*)END//gs) {
        # do something with $1
-    } 
+    }
 
 A more complicated and sneaky approach is to make Perl's regular
 expression engine do it for you.  This is courtesy Dean Inada, and
@@ -635,7 +683,7 @@ capabilities.
 
 You can access the first characters of a string with substr().
 To get the first character, for example, start at position 0
-and grab the string of length 1.  
+and grab the string of length 1.
 
 
        $string = "Just another Perl Hacker";
@@ -645,11 +693,11 @@ To change part of a string, you can use the optional fourth
 argument which is the replacement string.
 
     substr( $string, 13, 4, "Perl 5.8.0" );
-       
+
 You can also use substr() as an lvalue.
 
     substr( $string, 13, 4 ) =  "Perl 5.8.0";
-       
+
 =head2 How do I change the Nth occurrence of something?
 
 You have to keep track of N yourself.  For example, let's say you want
@@ -741,10 +789,23 @@ case", but that's not quite accurate.  Consider the proper
 capitalization of the movie I<Dr. Strangelove or: How I Learned to
 Stop Worrying and Love the Bomb>, for example.
 
+Damian Conway's L<Text::Autoformat> module provides some smart
+case transformations:
+
+    use Text::Autoformat;
+    my $x = "Dr. Strangelove or: How I Learned to Stop ".
+      "Worrying and Love the Bomb";
+
+    print $x, "\n";
+    for my $style (qw( sentence title highlight ))
+    {
+        print autoformat($x, { case => $style }), "\n";
+    }
+
 =head2 How can I split a [character] delimited string except when inside [character]?
 
 Several modules can handle this sort of pasing---Text::Balanced,
-Text::CVS, Text::CVS_XS, and Text::ParseWords, among others.
+Text::CSV, Text::CSV_XS, and Text::ParseWords, among others.
 
 Take the example case of trying to split a string that is
 comma-separated into its different fields. You can't use C<split(/,/)>
@@ -754,7 +815,7 @@ example, take a data line like this:
     SAR001,"","Cimetrix, Inc","Bob Smith","CAM",N,8,1,0,7,"Error, Core Dumped"
 
 Due to the restriction of the quotes, this is a fairly complex
-problem.  Thankfully, we have Jeffrey Friedl, author of 
+problem.  Thankfully, we have Jeffrey Friedl, author of
 I<Mastering Regular Expressions>, to handle these for us.  He
 suggests (assuming your string is contained in $text):
 
@@ -799,10 +860,10 @@ Or more nicely written as:
 
 This idiom takes advantage of the C<foreach> loop's aliasing
 behavior to factor out common code.  You can do this
-on several strings at once, or arrays, or even the 
+on several strings at once, or arrays, or even the
 values of a hash if you use a slice:
 
-    # trim whitespace in the scalar, the array, 
+    # trim whitespace in the scalar, the array,
     # and all the values in the hash
     foreach ($scalar, @array, @hash{keys %hash}) {
         s/^\s+//;
@@ -811,9 +872,6 @@ values of a hash if you use a slice:
 
 =head2 How do I pad a string with blanks or pad a number with zeroes?
 
-(This answer contributed by Uri Guttman, with kibitzing from
-Bart Lateur.) 
-
 In the following examples, C<$pad_len> is the length to which you wish
 to pad the string, C<$text> or C<$num> contains the string to be padded,
 and C<$pad_char> contains the padding character. You can use a single
@@ -828,13 +886,16 @@ right with blanks and it will truncate the result to a maximum length of
 C<$pad_len>.
 
     # Left padding a string with blanks (no truncation):
-    $padded = sprintf("%${pad_len}s", $text);
+       $padded = sprintf("%${pad_len}s", $text);
+       $padded = sprintf("%*s", $pad_len, $text);  # same thing
 
     # Right padding a string with blanks (no truncation):
-    $padded = sprintf("%-${pad_len}s", $text);
+       $padded = sprintf("%-${pad_len}s", $text);
+       $padded = sprintf("%-*s", $pad_len, $text); # same thing
 
-    # Left padding a number with 0 (no truncation): 
-    $padded = sprintf("%0${pad_len}d", $num);
+    # Left padding a number with 0 (no truncation):
+       $padded = sprintf("%0${pad_len}d", $num);
+       $padded = sprintf("%0*d", $pad_len, $num); # same thing
 
     # Right padding a string with blanks using pack (will truncate):
     $padded = pack("A$pad_len",$text);
@@ -857,19 +918,19 @@ Left and right padding with any character, modifying C<$text> directly:
 =head2 How do I extract selected columns from a string?
 
 Use substr() or unpack(), both documented in L<perlfunc>.
-If you prefer thinking in terms of columns instead of widths, 
+If you prefer thinking in terms of columns instead of widths,
 you can use this kind of thing:
 
     # determine the unpack format needed to split Linux ps output
     # arguments are cut columns
     my $fmt = cut2fmt(8, 14, 20, 26, 30, 34, 41, 47, 59, 63, 67, 72);
 
-    sub cut2fmt { 
+    sub cut2fmt {
        my(@positions) = @_;
        my $template  = '';
        my $lastpos   = 1;
        for my $place (@positions) {
-           $template .= "A" . ($place - $lastpos) . " "; 
+           $template .= "A" . ($place - $lastpos) . " ";
            $lastpos   = $place;
        }
        $template .= "A*";
@@ -878,50 +939,43 @@ you can use this kind of thing:
 
 =head2 How do I find the soundex value of a string?
 
-Use the standard Text::Soundex module distributed with Perl.
-Before you do so, you may want to determine whether `soundex' is in
-fact what you think it is.  Knuth's soundex algorithm compresses words
-into a small space, and so it does not necessarily distinguish between
-two words which you might want to appear separately.  For example, the
-last names `Knuth' and `Kant' are both mapped to the soundex code K530.
-If Text::Soundex does not do what you are looking for, you might want
-to consider the String::Approx module available at CPAN.
+(contributed by brian d foy)
+
+You can use the Text::Soundex module. If you want to do fuzzy or close
+matching, you might also try the String::Approx, and Text::Metaphone,
+and Text::DoubleMetaphone modules.
 
 =head2 How can I expand variables in text strings?
 
-Let's assume that you have a string like:
+Let's assume that you have a string that contains placeholder
+variables.
 
     $text = 'this has a $foo in it and a $bar';
 
-If those were both global variables, then this would
-suffice:
-
-    $text =~ s/\$(\w+)/${$1}/g;  # no /e needed
-
-But since they are probably lexicals, or at least, they could
-be, you'd have to do this:
+You can use a substitution with a double evaluation.  The
+first /e turns C<$1> into C<$foo>, and the second /e turns
+C<$foo> into its value.  You may want to wrap this in an
+C<eval>: if you try to get the value of an undeclared variable
+while running under C<use strict>, you get a fatal error.
 
-    $text =~ s/(\$\w+)/$1/eeg;
-    die if $@;                 # needed /ee, not /e
+    eval { $text =~ s/(\$\w+)/$1/eeg };
+    die if $@;
 
 It's probably better in the general case to treat those
 variables as entries in some special hash.  For example:
 
-    %user_defs = ( 
+    %user_defs = (
        foo  => 23,
        bar  => 19,
     );
     $text =~ s/\$(\w+)/$user_defs{$1}/g;
 
-See also ``How do I expand function calls in a string?'' in this section
-of the FAQ.
-
 =head2 What's wrong with always quoting "$vars"?
 
 The problem is that those double-quotes force stringification--
 coercing numbers and references into strings--even when you
 don't want them to be strings.  Think of it this way: double-quote
-expansion is used to produce new strings.  If you already 
+expansion is used to produce new strings.  If you already
 have a string, why do you need more?
 
 If you get used to writing odd things like these:
@@ -952,27 +1006,27 @@ that actually do care about the difference between a string and a
 number, such as the magical C<++> autoincrement operator or the
 syscall() function.
 
-Stringification also destroys arrays.  
+Stringification also destroys arrays.
 
     @lines = `command`;
     print "@lines";            # WRONG - extra blanks
     print @lines;              # right
 
-=head2 Why don't my <<HERE documents work?
+=head2 Why don't my E<lt>E<lt>HERE documents work?
 
 Check for these three things:
 
 =over 4
 
-=item 1. There must be no space after the << part.
+=item There must be no space after the E<lt>E<lt> part.
 
-=item 2. There (probably) should be a semicolon at the end.
+=item There (probably) should be a semicolon at the end.
 
-=item 3. You can't (easily) have any space in front of the tag.
+=item You can't (easily) have any space in front of the tag.
 
 =back
 
-If you want to indent the text in the here document, you 
+If you want to indent the text in the here document, you
 can do this:
 
     # all in one
@@ -982,7 +1036,7 @@ can do this:
     HERE_TARGET
 
 But the HERE_TARGET must still be flush against the margin.
-If you want that indented also, you'll have to quote 
+If you want that indented also, you'll have to quote
 in the indentation.
 
     ($quote = <<'    FINIS') =~ s/^\s+//gm;
@@ -1077,7 +1131,7 @@ with
 
     @bad[0]  = `same program that outputs several lines`;
 
-The C<use warnings> pragma and the B<-w> flag will warn you about these 
+The C<use warnings> pragma and the B<-w> flag will warn you about these
 matters.
 
 =head2 How can I remove duplicate elements from a list or array?
@@ -1233,8 +1287,8 @@ like this one.  It uses the CPAN module FreezeThaw:
     @a = @b = ( "this", "that", [ "more", "stuff" ] );
 
     printf "a and b contain %s arrays\n",
-        cmpStr(\@a, \@b) == 0 
-           ? "the same" 
+        cmpStr(\@a, \@b) == 0
+           ? "the same"
            : "different";
 
 This approach also works for comparing hashes.  Here
@@ -1244,7 +1298,7 @@ we'll demonstrate two different answers:
 
     %a = %b = ( "this" => "that", "extra" => [ "more", "stuff" ] );
     $a{EXTRA} = \%b;
-    $b{EXTRA} = \%a;                    
+    $b{EXTRA} = \%a;
 
     printf "a and b contain %s hashes\n",
        cmpStr(\%a, \%b) == 0 ? "the same" : "different";
@@ -1264,9 +1318,9 @@ use the first() function in the List::Util module, which comes with
 Perl 5.8.  This example finds the first element that contains "Perl".
 
        use List::Util qw(first);
-       
+
        my $element = first { /Perl/ } @array;
-       
+
 If you cannot use List::Util, you can make your own loop to do the
 same thing.  Once you find the element, you stop the loop with last.
 
@@ -1280,13 +1334,13 @@ If you want the array index, you can iterate through the indices
 and check the array element at each index until you find one
 that satisfies the condition.
 
-       my( $found, $i ) = ( undef, -1 );
-    for( $i = 0; $i < @array; $i++ ) 
+       my( $found, $index ) = ( undef, -1 );
+    for( $i = 0; $i < @array; $i++ )
        {
-        if( $array[$i] =~ /Perl/ ) 
-               { 
+        if( $array[$i] =~ /Perl/ )
+               {
                $found = $array[$i];
-               $index = $i; 
+               $index = $i;
                last;
                }
         }
@@ -1408,7 +1462,7 @@ Here's another; let's compute spherical volumes:
        $_ **= 3;
        $_ *= (4/3) * 3.14159;  # this will be constant folded
     }
-    
+
 which can also be done with map() which is made to transform
 one list into another:
 
@@ -1420,7 +1474,7 @@ the values are not copied, so if you modify $orbit (in this
 case), you modify the value.
 
     for $orbit ( values %orbits ) {
-       ($orbit **= 3) *= (4/3) * 3.14159; 
+       ($orbit **= 3) *= (4/3) * 3.14159;
     }
 
 Prior to perl 5.6 C<values> returned copies of the values,
@@ -1432,16 +1486,11 @@ the hash is to be modified.
 
 Use the rand() function (see L<perlfunc/rand>):
 
-    # at the top of the program:
-    srand;                     # not needed for 5.004 and later
-
-    # then later on
     $index   = rand @array;
     $element = $array[$index];
 
-Make sure you I<only call srand once per program, if then>.
-If you are calling it more than once (such as before each 
-call to rand), you're almost certainly doing something wrong.
+Or, simply:
+    my $element = $array[ rand @array ];
 
 =head2 How do I permute N elements of a list?
 
@@ -1456,6 +1505,14 @@ on CPAN).  It's written in XS code and is very efficient.
           print "next permutation: (@perm)\n";
        }
 
+For even faster execution, you could do:
+
+   use Algorithm::Permute;
+   my @array = 'a'..'d';
+   Algorithm::Permute::permute {
+      print "next permutation: (@array)\n";
+   } @array;
+
 Here's a little program that generates all permutations of
 all the words on each line of input. The algorithm embodied
 in the permute() function is discussed in Volume 4 (still
@@ -1521,7 +1578,7 @@ If you need to sort on several fields, the following paradigm is useful.
 This can be conveniently combined with precalculation of keys as given
 above.
 
-See the F<sort> artitcle article in the "Far More Than You Ever Wanted
+See the F<sort> article in the "Far More Than You Ever Wanted
 To Know" collection in http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz for
 more about this approach.
 
@@ -1585,13 +1642,13 @@ Or use the CPAN module Bit::Vector:
     @ints = $vector->Index_List_Read();
 
 Bit::Vector provides efficient methods for bit vector, sets of small integers
-and "big int" math. 
+and "big int" math.
 
 Here's a more extensive illustration using vec():
 
     # vec demo
     $vector = "\xff\x0f\xef\xfe";
-    print "Ilya's string \\xff\\x0f\\xef\\xfe represents the number ", 
+    print "Ilya's string \\xff\\x0f\\xef\\xfe represents the number ",
        unpack("N", $vector), "\n";
     $is_set = vec($vector, 23, 1);
     print "Its 23rd bit is ", $is_set ? "set" : "clear", ".\n";
@@ -1611,7 +1668,7 @@ Here's a more extensive illustration using vec():
     set_vec(0,32,17);
     set_vec(1,32,17);
 
-    sub set_vec { 
+    sub set_vec {
        my ($offset, $width, $value) = @_;
        my $vector = '';
        vec($vector, $offset, $width) = $value;
@@ -1628,7 +1685,7 @@ Here's a more extensive illustration using vec():
        print "vector length in bytes: ", length($vector), "\n";
        @bytes = unpack("A8" x length($vector), $bits);
        print "bits are: @bytes\n\n";
-    } 
+    }
 
 =head2 Why does defined() return true on empty arrays and hashes?
 
@@ -1652,19 +1709,15 @@ sorting the keys as shown in an earlier question.
 
 =head2 What happens if I add or remove keys from a hash while iterating over it?
 
-Don't do that. :-)
+(contributed by brian d foy)
 
-[lwall] In Perl 4, you were not allowed to modify a hash at all while
-iterating over it.  In Perl 5 you can delete from it, but you still
-can't add to it, because that might cause a doubling of the hash table,
-in which half the entries get copied up to the new top half of the
-table, at which point you've totally bamboozled the iterator code.
-Even if the table doesn't double, there's no telling whether your new
-entry will be inserted before or after the current iterator position.
+The easy answer is "Don't do that!"
 
-Either treasure up your changes and make them after the iterator finishes
-or use keys to fetch all the old keys at once, and iterate over the list
-of keys.
+If you iterate through the hash with each(), you can delete the key
+most recently returned without worrying about it.  If you delete or add
+other keys, the iterator may skip or double up on them since perl
+may rearrange the hash table.  See the
+entry for C<each()> in L<perlfunc>.
 
 =head2 How do I look up a hash element by value?
 
@@ -1695,8 +1748,8 @@ use the keys() function in a scalar context:
 
     $num_keys = keys %hash;
 
-The keys() function also resets the iterator, which means that you may 
-see strange results if you use this between uses of other hash operators 
+The keys() function also resets the iterator, which means that you may
+see strange results if you use this between uses of other hash operators
 such as each().
 
 =head2 How do I sort a hash (optionally by value instead of key)?
@@ -1862,7 +1915,7 @@ it on top of either DB_File or GDBM_File.
 Use the Tie::IxHash from CPAN.
 
     use Tie::IxHash;
-    tie my %myhash, Tie::IxHash;
+    tie my %myhash, 'Tie::IxHash';
     for (my $i=0; $i<20; $i++) {
         $myhash{$i} = 2*$i;
     }
@@ -1943,13 +1996,17 @@ Assuming that you don't care about IEEE notations like "NaN" or
    if (/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/)
                        { print "a C float\n" }
 
-You can also use the L<Data::Types|Data::Types> module on
-the CPAN, which exports functions that validate data types
-using these and other regular expressions, or you can use
-the C<Regexp::Common> module from CPAN which has regular
-expressions to match various types of numbers.
-
-If you're on a POSIX system, Perl's supports the C<POSIX::strtod>
+There are also some commonly used modules for the task.
+L<Scalar::Util> (distributed with 5.8) provides access to perl's
+internal function C<looks_like_number> for determining
+whether a variable looks like a number.  L<Data::Types>
+exports functions that validate data types using both the
+above and other regular expressions. Thirdly, there is
+C<Regexp::Common> which has regular expressions to match
+various types of numbers. Those three modules are available
+from the CPAN.
+
+If you're on a POSIX system, Perl supports the C<POSIX::strtod>
 function.  Its semantics are somewhat cumbersome, so here's a C<getnum>
 wrapper function for more convenient access.  This function takes
 a string and returns the number it found, or C<undef> for input that
@@ -1967,12 +2024,12 @@ if you just want to say, ``Is this a float?''
             return undef;
         } else {
             return $num;
-        } 
-    } 
+        }
+    }
 
-    sub is_numeric { defined getnum($_[0]) } 
+    sub is_numeric { defined getnum($_[0]) }
 
-Or you could check out the L<String::Scanf|String::Scanf> module on the CPAN
+Or you could check out the L<String::Scanf> module on the CPAN
 instead. The POSIX module (part of the standard Perl distribution) provides
 the C<strtod> and C<strtol> for converting strings to double and longs,
 respectively.
@@ -1985,20 +2042,21 @@ or Storable modules from CPAN.  Starting from Perl 5.8 Storable is part
 of the standard distribution.  Here's one example using Storable's C<store>
 and C<retrieve> functions:
 
-    use Storable; 
+    use Storable;
     store(\%hash, "filename");
 
-    # later on...  
+    # later on...
     $href = retrieve("filename");        # by ref
     %hash = %{ retrieve("filename") };   # direct to hash
 
 =head2 How do I print out or copy a recursive data structure?
 
 The Data::Dumper module on CPAN (or the 5.005 release of Perl) is great
-for printing out data structures.  The Storable module, found on CPAN,
-provides a function called C<dclone> that recursively copies its argument.
+for printing out data structures.  The Storable module on CPAN (or the
+5.8 release of Perl), provides a function called C<dclone> that recursively
+copies its argument.
 
-    use Storable qw(dclone); 
+    use Storable qw(dclone);
     $r2 = dclone($r1);
 
 Where $r1 can be a reference to any kind of data structure you'd like.
@@ -2024,8 +2082,8 @@ the PDL module from CPAN instead--it makes number-crunching easy.
 
 =head1 AUTHOR AND COPYRIGHT
 
-Copyright (c) 1997-2002 Tom Christiansen and Nathan Torkington.
-All rights reserved.
+Copyright (c) 1997-2005 Tom Christiansen, Nathan Torkington, and
+other authors as noted. All rights reserved.
 
 This documentation is free; you can redistribute it and/or modify it
 under the same terms as Perl itself.