[PATCH] perlcommunity.pod: add information about OSDC.fr
[p5sagit/p5-mst-13.2.git] / pod / perlfaq4.pod
index 633f5f1..8d93d3f 100644 (file)
 =head1 NAME
 
-perlfaq4 - Data Manipulation ($Revision: 1.26 $, $Date: 1998/08/05 12:04:00 $)
+perlfaq4 - Data Manipulation
 
 =head1 DESCRIPTION
 
-The section of the FAQ answers question related to the manipulation
-of data as numbers, dates, strings, arrays, hashes, and miscellaneous
-data issues.
+This section of the FAQ answers questions related to manipulating
+numbers, dates, strings, arrays, hashes, and miscellaneous data issues.
 
 =head1 Data: Numbers
 
 =head2 Why am I getting long decimals (eg, 19.9499999999999) instead of the numbers I should be getting (eg, 19.95)?
 
-The infinite set that a mathematician thinks of as the real numbers can
-only be approximate on a computer, since the computer only has a finite
-number of bits to store an infinite number of, um, numbers.
-
 Internally, your computer represents floating-point numbers in binary.
-Floating-point numbers read in from a file or appearing as literals
-in your program are converted from their decimal floating-point
-representation (eg, 19.95) to the internal binary representation.
-
-However, 19.95 can't be precisely represented as a binary
-floating-point number, just like 1/3 can't be exactly represented as a
-decimal floating-point number.  The computer's binary representation
-of 19.95, therefore, isn't exactly 19.95.
-
-When a floating-point number gets printed, the binary floating-point
-representation is converted back to decimal.  These decimal numbers
-are displayed in either the format you specify with printf(), or the
-current output format for numbers (see L<perlvar/"$#"> if you use
-print.  C<$#> has a different default value in Perl5 than it did in
-Perl4.  Changing C<$#> yourself is deprecated.
-
-This affects B<all> computer languages that represent decimal
-floating-point numbers in binary, not just Perl.  Perl provides
-arbitrary-precision decimal numbers with the Math::BigFloat module
-(part of the standard Perl distribution), but mathematical operations
-are consequently slower.
-
-To get rid of the superfluous digits, just use a format (eg,
-C<printf("%.2f", 19.95)>) to get the required precision.
-See L<perlop/"Floating-point Arithmetic">.
+Digital (as in powers of two) computers cannot store all numbers
+exactly.  Some real numbers lose precision in the process.  This is a
+problem with how computers store numbers and affects all computer
+languages, not just Perl.
+
+L<perlnumber> shows the gory details of number representations and
+conversions.
+
+To limit the number of decimal places in your numbers, you can use the
+printf or sprintf function.  See the L<"Floating Point
+Arithmetic"|perlop> for more details.
+
+       printf "%.2f", 10/3;
+
+       my $number = sprintf "%.2f", 10/3;
+
+=head2 Why is int() broken?
+
+Your C<int()> is most probably working just fine.  It's the numbers that
+aren't quite what you think.
+
+First, see the answer to "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 literals in your program.  If they are read in from somewhere and
-assigned, no automatic conversion takes place.  You must explicitly
-use oct() or hex() if you want the values converted.  oct() interprets
-both hex ("0x350") numbers and octal ones ("0350" or even without the
-leading "0", like "377"), while hex() only converts hexadecimal ones,
-with or without a leading "0x", like "0x255", "3A", "ff", or "deadbeef".
+(contributed by brian d foy)
+
+You're probably trying to convert a string to a number, which Perl only
+converts as a decimal number. When Perl converts a string to a number, it
+ignores leading spaces and zeroes, then assumes the rest of the digits
+are in base 10:
+
+       my $string = '0644';
+
+       print $string + 0;  # prints 644
+
+       print $string + 44; # prints 688, certainly not octal!
+
+This problem usually involves one of the Perl built-ins that has the
+same name a unix command that uses octal numbers as arguments on the
+command line. In this example, C<chmod> on the command line knows that
+its first argument is octal because that's what it does:
+
+       %prompt> chmod 644 file
+
+If you want to use the same literal digits (644) in Perl, you have to tell
+Perl to treat them as octal numbers either by prefixing the digits with
+a C<0> or using C<oct>:
+
+       chmod(     0644, $file);   # right, has leading zero
+       chmod( oct(644), $file );  # also correct
+
+The problem comes in when you take your numbers from something that Perl
+thinks is a string, such as a command line argument in C<@ARGV>:
+
+       chmod( $ARGV[0],      $file);   # wrong, even if "0644"
+
+       chmod( oct($ARGV[0]), $file );  # correct, treat string as octal
 
-This problem shows up most often when people try using chmod(), mkdir(),
-umask(), or sysopen(), which all want permissions in octal.
+You can always check the value you're using by printing it in octal
+notation to ensure it matches what you think it should be. Print it
+in octal  and decimal format:
 
-    chmod(644,  $file);        # WRONG -- perl -w catches this
-    chmod(0644, $file);        # right
+       printf "0%o %d", $number, $number;
 
-=head2 Does perl have a round function?  What about ceil() and floor()?  Trig functions?
+=head2 Does Perl have a round() function?  What about ceil() and floor()?  Trig functions?
 
-Remember that int() merely truncates toward 0.  For rounding to a
-certain number of digits, sprintf() or printf() is usually the easiest
-route.
+Remember that C<int()> merely truncates toward 0.  For rounding to a
+certain number of digits, C<sprintf()> or C<printf()> is usually the
+easiest route.
 
-    printf("%.3f", 3.1415926535);      # prints 3.142
+       printf("%.3f", 3.1415926535);   # prints 3.142
 
-The POSIX module (part of the standard perl distribution) implements
-ceil(), floor(), and a number of other mathematical and trigonometric
-functions.
+The C<POSIX> module (part of the standard Perl distribution)
+implements C<ceil()>, C<floor()>, and a number of other mathematical
+and trigonometric functions.
 
-    use POSIX;
-    $ceil   = ceil(3.5);                       # 4
-    $floor  = floor(3.5);                      # 3
+       use POSIX;
+       $ceil   = ceil(3.5);   # 4
+       $floor  = floor(3.5);  # 3
 
-In 5.000 to 5.003 Perls, trigonometry was done in the Math::Complex
-module.  With 5.004, the Math::Trig module (part of the standard perl
+In 5.000 to 5.003 perls, trigonometry was done in the C<Math::Complex>
+module.  With 5.004, the C<Math::Trig> module (part of the standard Perl
 distribution) implements the trigonometric functions. Internally it
-uses the Math::Complex module and some functions can break out from
+uses the C<Math::Complex> module and some functions can break out from
 the real axis into the complex plane, for example the inverse sine of
 2.
 
@@ -88,17 +117,183 @@ cases, it probably pays not to trust whichever system rounding is
 being used by Perl, but to instead implement the rounding function you
 need yourself.
 
-=head2 How do I convert bits into ints?
+To see why, notice how you'll still have an issue on half-way-point
+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.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. 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/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 between number
+representations.  This is intended to be representational rather than
+exhaustive.
+
+Some of the examples later in L<perlfaq4> use the C<Bit::Vector>
+module from CPAN. The reason you might choose C<Bit::Vector> over the
+perl built in functions is that it works with numbers of ANY size,
+that it is optimized for speed on some operations, and for at least
+some programmers the notation might be familiar.
+
+=over 4
+
+=item How do I convert hexadecimal into decimal
+
+Using perl's built in conversion of C<0x> notation:
+
+       $dec = 0xDEADBEEF;
+
+Using the C<hex> function:
+
+       $dec = hex("DEADBEEF");
+
+Using C<pack>:
+
+       $dec = unpack("N", pack("H8", substr("0" x 8 . "DEADBEEF", -8)));
+
+Using the CPAN module C<Bit::Vector>:
+
+       use Bit::Vector;
+       $vec = Bit::Vector->new_Hex(32, "DEADBEEF");
+       $dec = $vec->to_Dec();
+
+=item How do I convert from decimal to hexadecimal
+
+Using C<sprintf>:
+
+       $hex = sprintf("%X", 3735928559); # upper case A-F
+       $hex = sprintf("%x", 3735928559); # lower case a-f
+
+Using C<unpack>:
 
-To turn a string of 1s and 0s like C<10110110> into a scalar containing
-its binary value, use the pack() function (documented in
-L<perlfunc/"pack">):
+       $hex = unpack("H*", pack("N", 3735928559));
 
-    $decimal = pack('B8', '10110110');
+Using C<Bit::Vector>:
 
-Here's an example of going the other way:
+       use Bit::Vector;
+       $vec = Bit::Vector->new_Dec(32, -559038737);
+       $hex = $vec->to_Hex();
 
-    $binary_string = join('', unpack('B*', "\x29"));
+And C<Bit::Vector> supports odd bit counts:
+
+       use Bit::Vector;
+       $vec = Bit::Vector->new_Dec(33, 3735928559);
+       $vec->Resize(32); # suppress leading 0 if unwanted
+       $hex = $vec->to_Hex();
+
+=item How do I convert from octal to decimal
+
+Using Perl's built in conversion of numbers with leading zeros:
+
+       $dec = 033653337357; # note the leading 0!
+
+Using the C<oct> function:
+
+       $dec = oct("33653337357");
+
+Using C<Bit::Vector>:
+
+       use Bit::Vector;
+       $vec = Bit::Vector->new(32);
+       $vec->Chunk_List_Store(3, split(//, reverse "33653337357"));
+       $dec = $vec->to_Dec();
+
+=item How do I convert from decimal to octal
+
+Using C<sprintf>:
+
+       $oct = sprintf("%o", 3735928559);
+
+Using C<Bit::Vector>:
+
+       use Bit::Vector;
+       $vec = Bit::Vector->new_Dec(32, -559038737);
+       $oct = reverse join('', $vec->Chunk_List_Read(3));
+
+=item How do I convert from binary to decimal
+
+Perl 5.6 lets you write binary numbers directly with
+the C<0b> notation:
+
+       $number = 0b10110110;
+
+Using C<oct>:
+
+       my $input = "10110110";
+       $decimal = oct( "0b$input" );
+
+Using C<pack> and C<ord>:
+
+       $decimal = ord(pack('B8', '10110110'));
+
+Using C<pack> and C<unpack> for larger strings:
+
+       $int = unpack("N", pack("B32",
+       substr("0" x 32 . "11110101011011011111011101111", -32)));
+       $dec = sprintf("%d", $int);
+
+       # substr() is used to left pad a 32 character string with zeros.
+
+Using C<Bit::Vector>:
+
+       $vec = Bit::Vector->new_Bin(32, "11011110101011011011111011101111");
+       $dec = $vec->to_Dec();
+
+=item How do I convert from decimal to binary
+
+Using C<sprintf> (perl 5.6+):
+
+       $bin = sprintf("%b", 3735928559);
+
+Using C<unpack>:
+
+       $bin = unpack("B*", pack("N", 3735928559));
+
+Using C<Bit::Vector>:
+
+       use Bit::Vector;
+       $vec = Bit::Vector->new_Dec(32, -559038737);
+       $bin = $vec->to_Bin();
+
+The remaining transformations (e.g. hex -> oct, bin -> hex, etc.)
+are left as an exercise to the inclined reader.
+
+=back
+
+=head2 Why doesn't & work the way I want it to?
+
+The behavior of binary arithmetic operators depends on whether they're
+used on numbers or strings.  The operators treat a string as a series
+of bits and work with that (the string C<"3"> is the bit pattern
+C<00110011>).  The operators work with the binary form of a number
+(the number C<3> is treated as the bit pattern C<00000011>).
+
+So, saying C<11 & 3> performs the "and" operation on numbers (yielding
+C<3>).  Saying C<"11" & "3"> performs the "and" operation on strings
+(yielding C<"1">).
+
+Most problems with C<&> and C<|> arise because the programmer thinks
+they have a number but really it's a string.  The rest arise because
+the programmer says:
+
+       if ("\020\020" & "\101\101") {
+               # ...
+               }
+
+but a string consisting of two null bytes (the result of C<"\020\020"
+& "\101\101">) is not a false value in Perl.  You need:
+
+       if ( ("\020\020" & "\101\101") !~ /[^\000]/) {
+               # ...
+               }
 
 =head2 How do I multiply matrices?
 
@@ -110,114 +305,252 @@ or the PDL extension (also available from CPAN).
 To call a function on each element in an array, and collect the
 results, use:
 
-    @results = map { my_func($_) } @array;
+       @results = map { my_func($_) } @array;
 
 For example:
 
-    @triple = map { 3 * $_ } @single;
+       @triple = map { 3 * $_ } @single;
 
 To call a function on each element of an array, but ignore the
 results:
 
-    foreach $iterator (@array) {
-        &my_func($iterator);
-    }
+       foreach $iterator (@array) {
+               some_func($iterator);
+               }
 
 To call a function on each integer in a (small) range, you B<can> use:
 
-    @results = map { &my_func($_) } (5 .. 25);
+       @results = map { some_func($_) } (5 .. 25);
 
 but you should be aware that the C<..> operator creates an array of
 all integers in the range.  This can take a lot of memory for large
 ranges.  Instead use:
 
-    @results = ();
-    for ($i=5; $i < 500_005; $i++) {
-        push(@results, &my_func($i));
-    }
+       @results = ();
+       for ($i=5; $i < 500_005; $i++) {
+               push(@results, some_func($i));
+               }
+
+This situation has been fixed in Perl5.005. Use of C<..> in a C<for>
+loop will iterate over the range, without creating the entire range.
+
+       for my $i (5 .. 500_005) {
+               push(@results, some_func($i));
+               }
+
+will not create a list of 500,000 integers.
 
 =head2 How can I output Roman numerals?
 
-Get the http://www.perl.com/CPAN/modules/by-module/Roman module.
+Get the http://www.cpan.org/modules/by-module/Roman module.
 
 =head2 Why aren't my random numbers random?
 
-The short explanation is that you're getting pseudorandom numbers, not
-random ones, because computers are good at being predictable and bad
-at being random (despite appearances caused by bugs in your programs
-:-).  A longer explanation is available on
-http://www.perl.com/CPAN/doc/FMTEYEWTK/random, courtesy of Tom
-Phoenix.  John von Neumann said, ``Anyone who attempts to generate
-random numbers by deterministic means is, of course, living in a state
-of sin.''
-
-You should also check out the Math::TrulyRandom module from CPAN.  It
-uses the imperfections in your system's timer to generate random
-numbers, but this takes quite a while.  If you want a better
+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 }
+
+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 than more.
+
+Computers are good at being predictable and bad at being random
+(despite appearances caused by bugs in your programs :-).  see the
+F<random> article in the "Far More Than You Ever Wanted To Know"
+collection in http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz , courtesy
+of Tom Phoenix, talks more about this.  John von Neumann said, "Anyone
+who attempts to generate random numbers by deterministic means is, of
+course, living in a state of sin."
+
+If you want numbers that are more random than C<rand> with C<srand>
+provides, you should also check out the C<Math::TrulyRandom> module from
+CPAN.  It uses the imperfections in your system's timer to generate
+random numbers, but this takes quite a while.  If you want a better
 pseudorandom generator than comes with your operating system, look at
-``Numerical Recipes in C'' at http://nr.harvard.edu/nr/bookc.html .
+"Numerical Recipes in C" at http://www.nr.com/ .
+
+=head2 How do I get a random number between X and Y?
+
+To get a random number between two values, you can use the C<rand()>
+built-in to get a random number between 0 and 1. From there, you shift
+that into the range that you want.
+
+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 ); # ( 10,11,12,13,14, or 15 )
+
+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_between(50,120)>.
+
+       sub random_int_between {
+               my($min, $max) = @_;
+               # Assumes that the two arguments are integers themselves!
+               return $min if $min == $max;
+               ($min, $max) = ($max, $min)  if  $min > $max;
+               return $min + int rand(1 + $max - $min);
+               }
 
 =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 day of the year is in the array returned by localtime() (see
-L<perlfunc/"localtime">):
+The C<POSIX> module can also format a date as the day of the year or
+week of the year.
 
-    $day_of_year = (localtime(time()))[7];
+       use POSIX qw/strftime/;
+       my $day_of_year  = strftime "%j", localtime;
+       my $week_of_year = strftime "%W", localtime;
 
-or more legibly (in 5.004 or higher):
+To get the day of year for any date, use C<POSIX>'s C<mktime> to get
+a time in epoch seconds for the argument to localtime.
 
-    use Time::localtime;
-    $day_of_year = localtime(time())->yday;
+       use POSIX qw/mktime strftime/;
+       my $week_of_year = strftime "%W",
+               localtime( mktime( 0, 0, 0, 18, 11, 87 ) );
 
-You can find the week of the year by dividing this by 7:
+The C<Date::Calc> module provides two functions to calculate these.
 
-    $week_of_year = int($day_of_year / 7);
+       use Date::Calc;
+       my $day_of_year  = Day_of_Year(  1987, 12, 18 );
+       my $week_of_year = Week_of_Year( 1987, 12, 18 );
 
-Of course, this believes that weeks start at zero.  The Date::Calc
-module from CPAN has a lot of date calculation functions, including
-day of the year, week of the year, and so on.   Note that not
-all business consider ``week 1'' to be the same; for example,
-American business often consider the first week with a Monday
-in it to be Work Week #1, despite ISO 8601, which consider 
-WW1 to be the frist week with a Thursday in it.
+=head2 How do I find the current century or millennium?
+
+Use the following simple functions:
+
+       sub get_century    {
+               return int((((localtime(shift || time))[5] + 1999))/100);
+               }
+
+       sub get_millennium {
+               return 1+int((((localtime(shift || time))[5] + 1899))/1000);
+               }
+
+On some systems, the C<POSIX> module's C<strftime()> function has been
+extended in a non-standard way to use a C<%C> format, which they
+sometimes claim is the "century". It isn't, because on most such
+systems, this is only the first two digits of the four-digit year, and
+thus cannot be used to reliably determine the current century or
+millennium.
 
 =head2 How can I compare two dates and find the difference?
 
-If you're storing your dates as epoch seconds then simply subtract one
-from the other.  If you've got a structured date (distinct year, day,
-month, hour, minute, seconds values) then use one of the Date::Manip
-and Date::Calc modules from CPAN.
+(contributed by brian d foy)
+
+You could just store all your dates as a number and then subtract.
+Life isn't always that simple though. If you want to work with
+formatted dates, the C<Date::Manip>, C<Date::Calc>, or C<DateTime>
+modules can help you.
 
 =head2 How can I take a string and turn it into epoch seconds?
 
 If it's a regular enough string that it always has the same format,
 you can split it up and pass the parts to C<timelocal> in the standard
-Time::Local module.  Otherwise, you should look into the Date::Calc
-and Date::Manip modules from CPAN.
+C<Time::Local> module.  Otherwise, you should look into the C<Date::Calc>
+and C<Date::Manip> modules from CPAN.
 
 =head2 How can I find the Julian Day?
 
-Neither Date::Manip nor Date::Calc deal with Julian days.  Instead,
-there is an example of Julian date calculation that should help you in
-http://www.perl.com/CPAN/authors/David_Muir_Sharnoff/modules/Time/JulianDay.pm.gz
-.
+(contributed by brian d foy and Dave Cross)
+
+You can use the C<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 C<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?
+X<date> X<yesterday> X<DateTime> X<Date::Calc> X<Time::Local>
+X<daylight saving time> X<day> X<Today_and_Now> X<localtime>
+X<timelocal>
+
+(contributed by brian d foy)
+
+Use one of the Date modules. The C<DateTime> module makes it simple, and
+give you the same time of day, only the day before.
+
+       use DateTime;
+
+       my $yesterday = DateTime->now->subtract( days => 1 );
+
+       print "Yesterday was $yesterday\n";
+
+You can also use the C<Date::Calc> module using its C<Today_and_Now>
+function.
+
+       use Date::Calc qw( Today_and_Now Add_Delta_DHMS );
+
+       my @date_time = Add_Delta_DHMS( Today_and_Now(), -1, 0, 0, 0 );
+
+       print "@date_time\n";
+
+Most people try to use the time rather than the calendar to figure out
+dates, but that assumes that days are twenty-four hours each.  For
+most people, there are two days a year when they aren't: the switch to
+and from summer time throws this off. Let the modules do the work.
+
+If you absolutely must do it yourself (or can't use one of the
+modules), here's a solution using C<Time::Local>, which comes with
+Perl:
+
+       # contributed by Gunnar Hjalmarsson
+        use Time::Local;
+        my $today = timelocal 0, 0, 12, ( localtime )[3..5];
+        my ($d, $m, $y) = ( localtime $today-86400 )[3..5];
+        printf "Yesterday: %d-%02d-%02d\n", $y+1900, $m+1, $d;
+
+In this case, you measure the day starting at noon, and subtract 24
+hours. Even if the length of the calendar day is 23 or 25 hours,
+you'll still end up on the previous calendar day, although not at
+noon. Since you don't care about the time, the one hour difference
+doesn't matter and you end up with the previous date.
 
-=head2 Does Perl have a year 2000 problem?  Is Perl Y2K compliant?
+=head2 Does Perl have a Year 2000 problem? Is Perl Y2K compliant?
 
-Short answer: No, Perl does not have a Year 2000 problem.  Yes,
-Perl is Y2K compliant.  The programmers you're hired to use it,
-however, probably are not.
+Short answer: No, Perl does not have a Year 2000 problem.  Yes, Perl is
+Y2K compliant (whatever that means). The programmers you've hired to
+use it, however, probably are not.
 
-Long answer: Perl is just as Y2K compliant as your pencil--no more,
-and no less.  The date and time functions supplied with perl (gmtime
-and localtime) supply adequate information to determine the year well
-beyond 2000 (2038 is when trouble strikes for 32-bit machines).  The
-year returned by these functions when used in an array context is the
-year minus 1900.  For years between 1910 and 1999 this I<happens> to
-be a 2-digit decimal number. To avoid the year 2000 problem simply do
-not treat the year as a 2-digit number.  It isn't.
+Long answer: The question belies a true understanding of the issue.
+Perl is just as Y2K compliant as your pencil--no more, and no less.
+Can you use your pencil to write a non-Y2K-compliant memo?  Of course
+you can.  Is that the pencil's fault?  Of course it isn't.
+
+The date and time functions supplied with Perl (gmtime and localtime)
+supply adequate information to determine the year well beyond 2000
+(2038 is when trouble strikes for 32-bit machines).  The year returned
+by these functions when used in a list context is the year minus 1900.
+For years between 1910 and 1999 this I<happens> to be a 2-digit decimal
+number. To avoid the year 2000 problem simply do not treat the year as
+a 2-digit number.  It isn't.
 
 When gmtime() and localtime() are used in scalar context they return
 a timestamp string that contains a fully-expanded year.  For example,
@@ -226,52 +559,102 @@ 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
+not the language.  At the risk of inflaming the NRA: "Perl doesn't
+break Y2K, people do."  See http://www.perl.org/about/y2k.html for
 a longer exposition.
 
 =head1 Data: Strings
 
 =head2 How do I validate input?
 
-The answer to this question is usually a regular expression, perhaps
-with auxiliary logic.  See the more specific questions (numbers, mail
-addresses, etc.) for details.
+(contributed by brian d foy)
+
+There are many ways to ensure that values are what you expect or
+want to accept. Besides the specific examples that we cover in the
+perlfaq, you can also look at the modules with "Assert" and "Validate"
+in their names, along with other modules such as C<Regexp::Common>.
+
+Some modules have validation for particular types of input, such
+as C<Business::ISBN>, C<Business::CreditCard>, C<Email::Valid>,
+and C<Data::Validate::IP>.
 
 =head2 How do I unescape a string?
 
-It depends just what you mean by ``escape''.  URL escapes are dealt
+It depends just what you mean by "escape".  URL escapes are dealt
 with in L<perlfaq9>.  Shell escapes with the backslash (C<\>)
-character are removed with:
+character are removed with
 
-    s/\\(.)/$1/g;
+       s/\\(.)/$1/g;
 
 This won't expand C<"\n"> or C<"\t"> or any other special escapes.
 
 =head2 How do I remove consecutive pairs of characters?
 
-To turn C<"abbcccd"> into C<"abccd">:
+(contributed by brian d foy)
+
+You can use the substitution operator to find pairs of characters (or
+runs of characters) and replace them with a single instance. In this
+substitution, we find a character in C<(.)>. The memory parentheses
+store the matched character in the back-reference C<\1> and we use
+that to require that the same thing immediately follow it. We replace
+that part of the string with the character in C<$1>.
+
+       s/(.)\1/$1/g;
+
+We can also use the transliteration operator, C<tr///>. In this
+example, the search list side of our C<tr///> contains nothing, but
+the C<c> option complements that so it contains everything. The
+replacement list also contains nothing, so the transliteration is
+almost a no-op since it won't do any replacements (or more exactly,
+replace the character with itself). However, the C<s> option squashes
+duplicated and consecutive characters in the string so a character
+does not show up next to itself
 
-    s/(.)\1/$1/g;
+       my $str = 'Haarlem';   # in the Netherlands
+       $str =~ tr///cs;       # Now Harlem, like in New York
 
 =head2 How do I expand function calls in a string?
 
-This is documented in L<perlref>.  In general, this is fraught with
-quoting and readability problems, but it is possible.  To interpolate
-a subroutine call (in list context) into a string:
+(contributed by brian d foy)
+
+This is documented in L<perlref>, and although it's not the easiest
+thing to read, it does work. In each of these examples, we call the
+function inside the braces used to dereference a reference. If we
+have more than one return value, we can construct and dereference an
+anonymous array. In this case, we call the function in list context.
+
+       print "The time values are @{ [localtime] }.\n";
+
+If we want to call the function in scalar context, we have to do a bit
+more work. We can really have any code we like inside the braces, so
+we simply have to end with the scalar reference, although how you do
+that is up to you, and you can use code inside the braces. Note that
+the use of parens creates a list context, so we need C<scalar> to
+force the scalar context on the function:
+
+       print "The time is ${\(scalar localtime)}.\n"
+
+       print "The time is ${ my $x = localtime; \$x }.\n";
 
-    print "My sub returned @{[mysub(1,2,3)]} that time.\n";
+If your function already returns a reference, you don't need to create
+the reference yourself.
 
-If you prefer scalar context, similar chicanery is also useful for
-arbitrary expressions:
+       sub timestamp { my $t = localtime; \$t }
 
-    print "That yields ${\($n + 5)} widgets\n";
+       print "The time is ${ timestamp() }.\n";
 
-Version 5.004 of Perl had a bug that gave list context to the
-expression in C<${...}>, but this is fixed in version 5.005.
+The C<Interpolation> module can also do a lot of magic for you. You can
+specify a variable name, in this case C<E>, to set up a tied hash that
+does the interpolation for you. It has several other methods to do this
+as well.
 
-See also ``How can I expand variables in text strings?'' in this
-section of the FAQ.
+       use Interpolation E => 'eval';
+       print "The time values are $E{localtime()}.\n";
+
+In most cases, it is probably easier to simply use string concatenation,
+which also forces scalar context.
+
+       print "The time is " . localtime() . ".\n";
 
 =head2 How do I find matching/nesting anything?
 
@@ -279,108 +662,137 @@ This isn't something that can be done in one regular expression, no
 matter how complicated.  To find something between two single
 characters, a pattern like C</x([^x]*)x/> will get the intervening
 bits in $1. For multiple ones, then something more like
-C</alpha(.*?)omega/> would be needed.  But none of these deals with
-nested patterns, nor can they.  For that you'll have to write a
+C</alpha(.*?)omega/> would be needed. But none of these deals with
+nested patterns.  For balanced expressions using C<(>, C<{>, C<[> or
+C<< < >> as delimiters, use the CPAN module Regexp::Common, or see
+L<perlre/(??{ code })>.  For other cases, you'll have to write a
 parser.
 
 If you are serious about writing a parser, there are a number of
-modules or oddities that will make your life a lot easier.  There is
-the CPAN module Parse::RecDescent, the standard module Text::Balanced,
-the byacc program, and Mark-Jason Dominus's excellent I<py> tool at
-http://www.plover.com/~mjd/perl/py/ .
+modules or oddities that will make your life a lot easier.  There are
+the CPAN modules C<Parse::RecDescent>, C<Parse::Yapp>, and
+C<Text::Balanced>; and the C<byacc> program. Starting from perl 5.8
+the C<Text::Balanced> is part of the standard distribution.
 
 One simple destructive, inside-out approach that you might try is to
 pull out the smallest nesting parts one at a time:
 
-    while (s//BEGIN((?:(?!BEGIN)(?!END).)*)END/gs) {
-       # do something with $1
-    } 
+       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
+rather has the nature of an Obfuscated Perl Contest entry, but it
+really does work:
+
+       # $_ contains the string to parse
+       # BEGIN and END are the opening and closing markers for the
+       # nested text.
+
+       @( = ('(','');
+       @) = (')','');
+       ($re=$_)=~s/((BEGIN)|(END)|.)/$)[!$3]\Q$1\E$([!$2]/gs;
+       @$ = (eval{/$re/},$@!~/unmatched/i);
+       print join("\n",@$[0..$#$]) if( $$[-1] );
 
 =head2 How do I reverse a string?
 
-Use reverse() in scalar context, as documented in
+Use C<reverse()> in scalar context, as documented in
 L<perlfunc/reverse>.
 
-    $reversed = reverse $string;
+       $reversed = reverse $string;
 
 =head2 How do I expand tabs in a string?
 
 You can do it yourself:
 
-    1 while $string =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e;
+       1 while $string =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e;
 
-Or you can just use the Text::Tabs module (part of the standard perl
+Or you can just use the C<Text::Tabs> module (part of the standard Perl
 distribution).
 
-    use Text::Tabs;
-    @expanded_lines = expand(@lines_with_tabs);
+       use Text::Tabs;
+       @expanded_lines = expand(@lines_with_tabs);
 
 =head2 How do I reformat a paragraph?
 
-Use Text::Wrap (part of the standard perl distribution):
+Use C<Text::Wrap> (part of the standard Perl distribution):
 
-    use Text::Wrap;
-    print wrap("\t", '  ', @paragraphs);
+       use Text::Wrap;
+       print wrap("\t", '  ', @paragraphs);
 
-The paragraphs you give to Text::Wrap should not contain embedded
-newlines.  Text::Wrap doesn't justify the lines (flush-right).
+The paragraphs you give to C<Text::Wrap> should not contain embedded
+newlines.  C<Text::Wrap> doesn't justify the lines (flush-right).
 
-=head2 How can I access/change the first N letters of a string?
+Or use the CPAN module C<Text::Autoformat>.  Formatting files can be
+easily done by making a shell alias, like so:
 
-There are many ways.  If you just want to grab a copy, use
-substr():
+       alias fmt="perl -i -MText::Autoformat -n0777 \
+               -e 'print autoformat $_, {all=>1}' $*"
 
-    $first_byte = substr($a, 0, 1);
+See the documentation for C<Text::Autoformat> to appreciate its many
+capabilities.
 
-If you want to modify part of a string, the simplest way is often to
-use substr() as an lvalue:
+=head2 How can I access or change N characters of a string?
 
-    substr($a, 0, 3) = "Tom";
+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.
 
-Although those with a pattern matching kind of thought process will
-likely prefer:
 
-    $a =~ s/^.../Tom/;
+       $string = "Just another Perl Hacker";
+       $first_char = substr( $string, 0, 1 );  #  'J'
+
+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
 to change the fifth occurrence of C<"whoever"> or C<"whomever"> into
-C<"whosoever"> or C<"whomsoever">, case insensitively.
+C<"whosoever"> or C<"whomsoever">, case insensitively.  These
+all assume that $_ contains the string to be altered.
 
-    $count = 0;
-    s{((whom?)ever)}{
-       ++$count == 5           # is it the 5th?
-           ? "${2}soever"      # yes, swap
-           : $1                # renege and leave it there
-    }igex;
+       $count = 0;
+       s{((whom?)ever)}{
+       ++$count == 5       # is it the 5th?
+           ? "${2}soever"  # yes, swap
+           : $1            # renege and leave it there
+               }ige;
 
 In the more general case, you can use the C</g> modifier in a C<while>
 loop, keeping count of matches.
 
-    $WANT = 3;
-    $count = 0;
-    while (/(\w+)\s+fish\b/gi) {
-        if (++$count == $WANT) {
-            print "The third fish is a $1 one.\n";
-            # Warning: don't `last' out of this loop
-        }
-    }
+       $WANT = 3;
+       $count = 0;
+       $_ = "One fish two fish red fish blue fish";
+       while (/(\w+)\s+fish\b/gi) {
+               if (++$count == $WANT) {
+                       print "The third fish is a $1 one.\n";
+                       }
+               }
 
 That prints out: C<"The third fish is a red one.">  You can also use a
 repetition count and repeated pattern like this:
 
-    /(?:\w+\s+fish\s+){2}(\w+)\s+fish/i;
+       /(?:\w+\s+fish\s+){2}(\w+)\s+fish/i;
 
 =head2 How can I count the number of occurrences of a substring within a string?
 
-There are a number of ways, with varying efficiency: If you want a
+There are a number of ways, with varying efficiency.  If you want a
 count of a certain single character (X) within a string, you can use the
 C<tr///> function like so:
 
-    $string = "ThisXlineXhasXsomeXx'sXinXit":
-    $count = ($string =~ tr/X//);
-    print "There are $count X charcters in the string";
+       $string = "ThisXlineXhasXsomeXx'sXinXit";
+       $count = ($string =~ tr/X//);
+       print "There are $count X characters in the string";
 
 This is fine if you are just looking for a single character.  However,
 if you are trying to count multiple character substrings within a
@@ -388,216 +800,339 @@ larger string, C<tr///> won't work.  What you can do is wrap a while()
 loop around a global pattern match.  For example, let's count negative
 integers:
 
-    $string = "-9 55 48 -2 23 -76 4 14 -44";
-    while ($string =~ /-\d+/g) { $count++ }
-    print "There are $count negative numbers in the string";
+       $string = "-9 55 48 -2 23 -76 4 14 -44";
+       while ($string =~ /-\d+/g) { $count++ }
+       print "There are $count negative numbers in the string";
+
+Another version uses a global match in list context, then assigns the
+result to a scalar, producing a count of the number of matches.
+
+       $count = () = $string =~ /-\d+/g;
 
 =head2 How do I capitalize all the words on one line?
+X<Text::Autoformat> X<capitalize> X<case, title> X<case, sentence>
 
-To make the first letter of each word upper case:
+(contributed by brian d foy)
 
-        $line =~ s/\b(\w)/\U$1/g;
+Damian Conway's L<Text::Autoformat> handles all of the thinking
+for you.
 
-This has the strange effect of turning "C<don't do it>" into "C<Don'T
-Do It>".  Sometimes you might want this, instead (Suggested by Brian
-Foy):
+       use Text::Autoformat;
+       my $x = "Dr. Strangelove or: How I Learned to Stop ".
+         "Worrying and Love the Bomb";
 
-    $string =~ s/ (
-                 (^\w)    #at the beginning of the line
-                   |      # or
-                 (\s\w)   #preceded by whitespace
-                   )
-                /\U$1/xg;
-    $string =~ /([\w']+)/\u\L$1/g;
+       print $x, "\n";
+       for my $style (qw( sentence title highlight )) {
+               print autoformat($x, { case => $style }), "\n";
+               }
 
-To make the whole line upper case:
+How do you want to capitalize those words?
 
-        $line = uc($line);
+       FRED AND BARNEY'S LODGE        # all uppercase
+       Fred And Barney's Lodge        # title case
+       Fred and Barney's Lodge        # highlight case
 
-To force each word to be lower case, with the first letter upper case:
+It's not as easy a problem as it looks. How many words do you think
+are in there? Wait for it... wait for it.... If you answered 5
+you're right. Perl words are groups of C<\w+>, but that's not what
+you want to capitalize. How is Perl supposed to know not to capitalize
+that C<s> after the apostrophe? You could try a regular expression:
 
-        $line =~ s/(\w+)/\u\L$1/g;
+       $string =~ s/ (
+                                (^\w)    #at the beginning of the line
+                                  |      # or
+                                (\s\w)   #preceded by whitespace
+                                  )
+                               /\U$1/xg;
 
-You can (and probably should) enable locale awareness of those
-characters by placing a C<use locale> pragma in your program.
-See L<perllocale> for endless details on locales.
+       $string =~ s/([\w']+)/\u\L$1/g;
 
-=head2 How can I split a [character] delimited string except when inside
-[character]? (Comma-separated files)
+Now, what if you don't want to capitalize that "and"? Just use
+L<Text::Autoformat> and get on with the next problem. :)
 
-Take the example case of trying to split a string that is comma-separated
-into its different fields.  (We'll pretend you said comma-separated, not
-comma-delimited, which is different and almost never what you mean.) You
-can't use C<split(/,/)> because you shouldn't split if the comma is inside
-quotes.  For example, take a data line like this:
+=head2 How can I split a [character] delimited string except when inside [character]?
 
-    SAR001,"","Cimetrix, Inc","Bob Smith","CAM",N,8,1,0,7,"Error, Core Dumped"
+Several modules can handle this sort of parsing--C<Text::Balanced>,
+C<Text::CSV>, C<Text::CSV_XS>, and C<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(/,/)>
+because you shouldn't split if the comma is inside quotes.  For
+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 a highly
-recommended book on regular expressions, to handle these for us.  He
-suggests (assuming your string is contained in $text):
-
-     @new = ();
-     push(@new, $+) while $text =~ m{
-         "([^\"\\]*(?:\\.[^\"\\]*)*)",?  # groups the phrase inside the quotes
-       | ([^,]+),?
-       | ,
-     }gx;
-     push(@new, undef) if substr($text,-1,1) eq ',';
+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 C<$text>):
+
+        @new = ();
+        push(@new, $+) while $text =~ m{
+                "([^\"\\]*(?:\\.[^\"\\]*)*)",?  # groups the phrase inside the quotes
+               | ([^,]+),?
+               | ,
+               }gx;
+        push(@new, undef) if substr($text,-1,1) eq ',';
 
 If you want to represent quotation marks inside a
 quotation-mark-delimited field, escape them with backslashes (eg,
-C<"like \"this\"">.  Unescaping them is a task addressed earlier in
-this section.
+C<"like \"this\"">.
 
-Alternatively, the Text::ParseWords module (part of the standard perl
-distribution) lets you say:
+Alternatively, the C<Text::ParseWords> module (part of the standard
+Perl distribution) lets you say:
 
-    use Text::ParseWords;
-    @new = quotewords(",", 0, $text);
+       use Text::ParseWords;
+       @new = quotewords(",", 0, $text);
 
 =head2 How do I strip blank space from the beginning/end of a string?
 
-Although the simplest approach would seem to be:
+(contributed by brian d foy)
 
-    $string =~ s/^\s*(.*?)\s*$/$1/;
+A substitution can do this for you. For a single line, you want to
+replace all the leading or trailing whitespace with nothing. You
+can do that with a pair of substitutions.
 
-This is unneccesarily slow, destructive, and fails with embedded newlines.
-It is much better faster to do this in two steps:
+       s/^\s+//;
+       s/\s+$//;
 
-    $string =~ s/^\s+//;
-    $string =~ s/\s+$//;
+You can also write that as a single substitution, although it turns
+out the combined statement is slower than the separate ones. That
+might not matter to you, though.
 
-Or more nicely written as:
+       s/^\s+|\s+$//g;
 
-    for ($string) {
-       s/^\s+//;
-       s/\s+$//;
-    }
+In this regular expression, the alternation matches either at the
+beginning or the end of the string since the anchors have a lower
+precedence than the alternation. With the C</g> flag, the substitution
+makes all possible matches, so it gets both. Remember, the trailing
+newline matches the C<\s+>, and  the C<$> anchor can match to the
+physical end of the string, so the newline disappears too. Just add
+the newline to the output, which has the added benefit of preserving
+"blank" (consisting entirely of whitespace) lines which the C<^\s+>
+would remove all by itself.
 
-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 
-values of a hash if you use a slide:
+       while( <> )
+               {
+               s/^\s+|\s+$//g;
+               print "$_\n";
+               }
 
-    # trim whitespace in the scalar, the array, 
-    # and all the values in the hash
-    foreach ($scalar, @array, @hash{keys %hash}) {
-        s/^\s+//;
-        s/\s+$//;
-    }
+For a multi-line string, you can apply the regular expression
+to each logical line in the string by adding the C</m> flag (for
+"multi-line"). With the C</m> flag, the C<$> matches I<before> an
+embedded newline, so it doesn't remove it. It still removes the
+newline at the end of the string.
+
+       $string =~ s/^\s+|\s+$//gm;
+
+Remember that lines consisting entirely of whitespace will disappear,
+since the first part of the alternation can match the entire string
+and replace it with nothing. If need to keep embedded blank lines,
+you have to do a little more work. Instead of matching any whitespace
+(since that includes a newline), just match the other whitespace.
+
+       $string =~ s/^[\t\f ]+|[\t\f ]+$//mg;
+
+=head2 How do I pad a string with blanks or pad a number with zeroes?
+
+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
+character string constant instead of the C<$pad_char> variable if you
+know what it is in advance. And in the same way you can use an integer in
+place of C<$pad_len> if you know the pad length in advance.
+
+The simplest method uses the C<sprintf> function. It can pad on the left
+or right with blanks and on the left with zeroes and it will not
+truncate the result. The C<pack> function can only pad strings on the
+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("%*s", $pad_len, $text);  # same thing
+
+       # Right padding a string with blanks (no truncation):
+       $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);
+       $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);
+
+If you need to pad with a character other than blank or zero you can use
+one of the following methods.  They all generate a pad string with the
+C<x> operator and combine that with C<$text>. These methods do
+not truncate C<$text>.
+
+Left and right padding with any character, creating a new string:
+
+       $padded = $pad_char x ( $pad_len - length( $text ) ) . $text;
+       $padded = $text . $pad_char x ( $pad_len - length( $text ) );
+
+Left and right padding with any character, modifying C<$text> directly:
+
+       substr( $text, 0, 0 ) = $pad_char x ( $pad_len - length( $text ) );
+       $text .= $pad_char x ( $pad_len - length( $text ) );
 
 =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, 
-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 { 
-       my(@positions) = @_;
-       my $template  = '';
-       my $lastpos   = 1;
-       for my $place (@positions) {
-           $template .= "A" . ($place - $lastpos) . " "; 
-           $lastpos   = $place;
-       }
-       $template .= "A*";
-       return $template;
-    }
+(contributed by brian d foy)
+
+If you know where the columns that contain the data, you can
+use C<substr> to extract a single column.
+
+       my $column = substr( $line, $start_column, $length );
+
+You can use C<split> if the columns are separated by whitespace or
+some other delimiter, as long as whitespace or the delimiter cannot
+appear as part of the data.
+
+       my $line    = ' fred barney   betty   ';
+       my @columns = split /\s+/, $line;
+               # ( '', 'fred', 'barney', 'betty' );
+
+       my $line    = 'fred||barney||betty';
+       my @columns = split /\|/, $line;
+               # ( 'fred', '', 'barney', '', 'betty' );
+
+If you want to work with comma-separated values, don't do this since
+that format is a bit more complicated. Use one of the modules that
+handle that format, such as C<Text::CSV>, C<Text::CSV_XS>, or
+C<Text::CSV_PP>.
+
+If you want to break apart an entire line of fixed columns, you can use
+C<unpack> with the A (ASCII) format. by using a number after the format
+specifier, you can denote the column width. See the C<pack> and C<unpack>
+entries in L<perlfunc> for more details.
+
+       my @fields = unpack( $line, "A8 A8 A8 A16 A4" );
+
+Note that spaces in the format argument to C<unpack> do not denote literal
+spaces. If you have space separated data, you may want C<split> instead.
 
 =head2 How do I find the soundex value of a string?
 
-Use the standard Text::Soundex module distributed with perl.
+(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 C<String::Approx>, and
+C<Text::Metaphone>, and C<Text::DoubleMetaphone> modules.
 
 =head2 How can I expand variables in text strings?
 
-Let's assume that you have a string like:
+(contributed by brian d foy)
 
-    $text = 'this has a $foo in it and a $bar';
+If you can avoid it, don't, or if you can use a templating system,
+such as C<Text::Template> or C<Template> Toolkit, do that instead. You
+might even be able to get the job done with C<sprintf> or C<printf>:
 
-If those were both global variables, then this would
-suffice:
+       my $string = sprintf 'Say hello to %s and %s', $foo, $bar;
 
-    $text =~ s/\$(\w+)/${$1}/g;
+However, for the one-off simple case where I don't want to pull out a
+full templating system, I'll use a string that has two Perl scalar
+variables in it. In this example, I want to expand C<$foo> and C<$bar>
+to their variable's values:
 
-But since they are probably lexicals, or at least, they could
-be, you'd have to do this:
+       my $foo = 'Fred';
+       my $bar = 'Barney';
+       $string = 'Say hello to $foo and $bar';
 
-    $text =~ s/(\$\w+)/$1/eeg;
-    die if $@;                 # needed on /ee, not /e
+One way I can do this involves the substitution operator and a double
+C</e> flag.  The first C</e> evaluates C<$1> on the replacement side and
+turns it into C<$foo>. The second /e starts with C<$foo> and replaces
+it with its value. C<$foo>, then, turns into 'Fred', and that's finally
+what's left in the string:
 
-It's probably better in the general case to treat those
-variables as entries in some special hash.  For example:
+       $string =~ s/(\$\w+)/$1/eeg; # 'Say hello to Fred and Barney'
 
-    %user_defs = ( 
-       foo  => 23,
-       bar  => 19,
-    );
-    $text =~ s/\$(\w+)/$user_defs{$1}/g;
+The C</e> will also silently ignore violations of strict, replacing
+undefined variable names with the empty string. Since I'm using the
+C</e> flag (twice even!), I have all of the same security problems I
+have with C<eval> in its string form. If there's something odd in
+C<$foo>, perhaps something like C<@{[ system "rm -rf /" ]}>, then
+I could get myself in trouble.
 
-See also ``How do I expand function calls in a string?'' in this section
-of the FAQ.
+To get around the security problem, I could also pull the values from
+a hash instead of evaluating variable names. Using a single C</e>, I
+can check the hash to ensure the value exists, and if it doesn't, I
+can replace the missing value with a marker, in this case C<???> to
+signal that I missed something:
+
+       my $string = 'This has $foo and $bar';
+
+       my %Replacements = (
+               foo  => 'Fred',
+               );
+
+       # $string =~ s/\$(\w+)/$Replacements{$1}/g;
+       $string =~ s/\$(\w+)/
+               exists $Replacements{$1} ? $Replacements{$1} : '???'
+               /eg;
+
+       print $string;
 
 =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.
+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
+have a string, why do you need more?
 
 If you get used to writing odd things like these:
 
-    print "$var";      # BAD
-    $new = "$old";     # BAD
-    somefunc("$var");  # BAD
+       print "$var";           # BAD
+       $new = "$old";          # BAD
+       somefunc("$var");       # BAD
 
 You'll be in trouble.  Those should (in 99.8% of the cases) be
 the simpler and more direct:
 
-    print $var;
-    $new = $old;
-    somefunc($var);
+       print $var;
+       $new = $old;
+       somefunc($var);
 
 Otherwise, besides slowing you down, you're going to break code when
 the thing in the scalar is actually neither a string nor a number, but
 a reference:
 
-    func(\@array);
-    sub func {
-       my $aref = shift;
-       my $oref = "$aref";  # WRONG
-    }
+       func(\@array);
+       sub func {
+               my $aref = shift;
+               my $oref = "$aref";  # WRONG
+               }
 
 You can also get into subtle problems on those few operations in Perl
 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
+       @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
@@ -607,7 +1142,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;
@@ -616,18 +1151,18 @@ in the indentation.
             would deliver us. You are a liar, Saruman, and a corrupter
             of men's hearts.  --Theoden in /usr/src/perl/taint.c
         FINIS
-    $quote =~ s/\s*--/\n--/;
+    $quote =~ s/\s+--/\n--/;
 
 A nice general-purpose fixer-upper function for indented here documents
 follows.  It expects to be called with a here document as its argument.
 It looks to see whether each line begins with a common substring, and
-if so, strips that off.  Otherwise, it takes the amount of leading
-white space found on the first line and removes that much off each
+if so, strips that substring off.  Otherwise, it takes the amount of leading
+whitespace found on the first line and removes that much off each
 subsequent line.
 
     sub fix {
         local $_ = shift;
-        my ($white, $leader);  # common white space and common leading string
+        my ($white, $leader);  # common whitespace and common leading string
         if (/^\s*(?:([^\w\s]+)(\s*).*\n)(?:\s*\1\2?.*\n)+$/) {
             ($white, $leader) = ($2, quotemeta($1));
         } else {
@@ -639,21 +1174,21 @@ subsequent line.
 
 This works with leading special strings, dynamically determined:
 
-    $remember_the_main = fix<<'    MAIN_INTERPRETER_LOOP';
+       $remember_the_main = fix<<'    MAIN_INTERPRETER_LOOP';
        @@@ int
        @@@ runops() {
        @@@     SAVEI32(runlevel);
        @@@     runlevel++;
-       @@@     while ( op = (*op->op_ppaddr)() ) ;
+       @@@     while ( op = (*op->op_ppaddr)() );
        @@@     TAINT_NOT;
        @@@     return 0;
        @@@ }
-    MAIN_INTERPRETER_LOOP
+       MAIN_INTERPRETER_LOOP
 
-Or with a fixed amount of leading white space, with remaining
+Or with a fixed amount of leading whitespace, with remaining
 indentation correctly preserved:
 
-    $poem = fix<<EVER_ON_AND_ON;
+       $poem = fix<<EVER_ON_AND_ON;
        Now far ahead the Road has gone,
          And I must follow, if I can,
        Pursuing it with eager feet,
@@ -661,13 +1196,34 @@ indentation correctly preserved:
        Where many paths and errands meet.
          And whither then? I cannot say.
                --Bilbo in /usr/src/perl/pp_ctl.c
-    EVER_ON_AND_ON
+       EVER_ON_AND_ON
 
 =head1 Data: Arrays
 
+=head2 What is the difference between a list and an array?
+
+An array has a changeable length.  A list does not.  An array is
+something you can push or pop, while a list is a set of values.  Some
+people make the distinction that a list is a value while an array is a
+variable. Subroutines are passed and return lists, you put things into
+list context, you initialize arrays with lists, and you C<foreach()>
+across a list.  C<@> variables are arrays, anonymous arrays are
+arrays, arrays in scalar context behave like the number of elements in
+them, subroutines access their arguments through the array C<@_>, and
+C<push>/C<pop>/C<shift> only work on arrays.
+
+As a side note, there's no such thing as a list in scalar context.
+When you say
+
+       $scalar = (2, 5, 7, 9);
+
+you're using the comma operator in scalar context, so it uses the scalar
+comma operator.  There never was a list there at all! This causes the
+last value to be returned: 9.
+
 =head2 What is the difference between $array[1] and @array[1]?
 
-The former is a scalar value, the latter an array slice, which makes
+The former is a scalar value; the latter an array slice, making
 it a list with one (scalar) value.  You should use $ when you want a
 scalar value (most of the time) and @ when you want a list with one
 scalar value in it (very, very rarely; nearly never, in fact).
@@ -675,255 +1231,521 @@ scalar value in it (very, very rarely; nearly never, in fact).
 Sometimes it doesn't make a difference, but sometimes it does.
 For example, compare:
 
-    $good[0] = `some program that outputs several lines`;
+       $good[0] = `some program that outputs several lines`;
 
 with
 
-    @bad[0]  = `same program that outputs several lines`;
+       @bad[0]  = `same program that outputs several lines`;
 
-The B<-w> flag will warn you about these matters.
+The C<use warnings> pragma and the B<-w> flag will warn you about these
+matters.
 
-=head2 How can I extract just the unique elements of an array?
+=head2 How can I remove duplicate elements from a list or array?
 
-There are several possible ways, depending on whether the array is
-ordered and whether you wish to preserve the ordering.
+(contributed by brian d foy)
 
-=over 4
+Use a hash. When you think the words "unique" or "duplicated", think
+"hash keys".
 
-=item a) If @in is sorted, and you want @out to be sorted:
-(this assumes all true values in the array)
+If you don't care about the order of the elements, you could just
+create the hash then extract the keys. It's not important how you
+create that hash: just that you use C<keys> to get the unique
+elements.
 
-    $prev = 'nonesuch';
-    @out = grep($_ ne $prev && ($prev = $_), @in);
+       my %hash   = map { $_, 1 } @array;
+       # or a hash slice: @hash{ @array } = ();
+       # or a foreach: $hash{$_} = 1 foreach ( @array );
 
-This is nice in that it doesn't use much extra memory, simulating
-uniq(1)'s behavior of removing only adjacent duplicates.  It's less
-nice in that it won't work with false values like undef, 0, or "";
-"0 but true" is ok, though.
+       my @unique = keys %hash;
 
-=item b) If you don't know whether @in is sorted:
+If you want to use a module, try the C<uniq> function from
+C<List::MoreUtils>. In list context it returns the unique elements,
+preserving their order in the list. In scalar context, it returns the
+number of unique elements.
 
-    undef %saw;
-    @out = grep(!$saw{$_}++, @in);
+       use List::MoreUtils qw(uniq);
 
-=item c) Like (b), but @in contains only small integers:
+       my @unique = uniq( 1, 2, 3, 4, 4, 5, 6, 5, 7 ); # 1,2,3,4,5,6,7
+       my $unique = uniq( 1, 2, 3, 4, 4, 5, 6, 5, 7 ); # 7
 
-    @out = grep(!$saw[$_]++, @in);
+You can also go through each element and skip the ones you've seen
+before. Use a hash to keep track. The first time the loop sees an
+element, that element has no key in C<%Seen>. The C<next> statement
+creates the key and immediately uses its value, which is C<undef>, so
+the loop continues to the C<push> and increments the value for that
+key. The next time the loop sees that same element, its key exists in
+the hash I<and> the value for that key is true (since it's not 0 or
+C<undef>), so the next skips that iteration and the loop goes to the
+next element.
 
-=item d) A way to do (b) without any loops or greps:
+       my @unique = ();
+       my %seen   = ();
 
-    undef %saw;
-    @saw{@in} = ();
-    @out = sort keys %saw;  # remove sort if undesired
+       foreach my $elem ( @array )
+               {
+               next if $seen{ $elem }++;
+               push @unique, $elem;
+               }
 
-=item e) Like (d), but @in contains only small positive integers:
+You can write this more briefly using a grep, which does the
+same thing.
 
-    undef @ary;
-    @ary[@in] = @in;
-    @out = @ary;
+       my %seen = ();
+       my @unique = grep { ! $seen{ $_ }++ } @array;
 
-=back
+=head2 How can I tell whether a certain element is contained in a list or array?
 
-=head2 How can I tell whether a list or array contains a certain element?
+(portions of this answer contributed by Anno Siegel and brian d foy)
 
 Hearing the word "in" is an I<in>dication that you probably should have
 used a hash, not a list or array, to store your data.  Hashes are
 designed to answer this question quickly and efficiently.  Arrays aren't.
 
-That being said, there are several ways to approach this.  If you
+That being said, there are several ways to approach this.  In Perl 5.10
+and later, you can use the smart match operator to check that an item is
+contained in an array or a hash:
+
+       use 5.010;
+
+       if( $item ~~ @array )
+               {
+               say "The array contains $item"
+               }
+
+       if( $item ~~ %hash )
+               {
+               say "The hash contains $item"
+               }
+
+With earlier versions of Perl, you have to do a bit more work. If you
 are going to make this query many times over arbitrary string values,
-the fastest way is probably to invert the original array and keep an
-associative array lying about whose keys are the first array's values.
+the fastest way is probably to invert the original array and maintain a
+hash whose keys are the first array's values:
 
-    @blues = qw/azure cerulean teal turquoise lapis-lazuli/;
-    undef %is_blue;
-    for (@blues) { $is_blue{$_} = 1 }
+       @blues = qw/azure cerulean teal turquoise lapis-lazuli/;
+       %is_blue = ();
+       for (@blues) { $is_blue{$_} = 1 }
 
-Now you can check whether $is_blue{$some_color}.  It might have been a
-good idea to keep the blues all in a hash in the first place.
+Now you can check whether C<$is_blue{$some_color}>.  It might have
+been a good idea to keep the blues all in a hash in the first place.
 
 If the values are all small integers, you could use a simple indexed
 array.  This kind of an array will take up less space:
 
-    @primes = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31);
-    undef @is_tiny_prime;
-    for (@primes) { $is_tiny_prime[$_] = 1; }
+       @primes = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31);
+       @is_tiny_prime = ();
+       for (@primes) { $is_tiny_prime[$_] = 1 }
+       # or simply  @istiny_prime[@primes] = (1) x @primes;
 
 Now you check whether $is_tiny_prime[$some_number].
 
 If the values in question are integers instead of strings, you can save
 quite a lot of space by using bit strings instead:
 
-    @articles = ( 1..10, 150..2000, 2017 );
-    undef $read;
-    for (@articles) { vec($read,$_,1) = 1 }
+       @articles = ( 1..10, 150..2000, 2017 );
+       undef $read;
+       for (@articles) { vec($read,$_,1) = 1 }
 
 Now check whether C<vec($read,$n,1)> is true for some C<$n>.
 
-Please do not use
+These methods guarantee fast individual tests but require a re-organization
+of the original list or array.  They only pay off if you have to test
+multiple values against the same array.
+
+If you are testing only once, the standard module C<List::Util> exports
+the function C<first> for this purpose.  It works by stopping once it
+finds the element. It's written in C for speed, and its Perl equivalent
+looks like this subroutine:
+
+       sub first (&@) {
+               my $code = shift;
+               foreach (@_) {
+                       return $_ if &{$code}();
+               }
+               undef;
+       }
 
-    $is_there = grep $_ eq $whatever, @array;
+If speed is of little concern, the common idiom uses grep in scalar context
+(which returns the number of items that passed its condition) to traverse the
+entire list. This does have the benefit of telling you how many matches it
+found, though.
 
-or worse yet
+       my $is_there = grep $_ eq $whatever, @array;
 
-    $is_there = grep /$whatever/, @array;
+If you want to actually extract the matching elements, simply use grep in
+list context.
 
-These are slow (checks every element even if the first matches),
-inefficient (same reason), and potentially buggy (what if there are
-regexp characters in $whatever?).
+       my @matches = grep $_ eq $whatever, @array;
 
 =head2 How do I compute the difference of two arrays?  How do I compute the intersection of two arrays?
 
-Use a hash.  Here's code to do both and more.  It assumes that
-each element is unique in a given array:
+Use a hash.  Here's code to do both and more.  It assumes that each
+element is unique in a given array:
 
-    @union = @intersection = @difference = ();
-    %count = ();
-    foreach $element (@array1, @array2) { $count{$element}++ }
-    foreach $element (keys %count) {
-       push @union, $element;
-       push @{ $count{$element} > 1 ? \@intersection : \@difference }, $element;
-    }
+       @union = @intersection = @difference = ();
+       %count = ();
+       foreach $element (@array1, @array2) { $count{$element}++ }
+       foreach $element (keys %count) {
+               push @union, $element;
+               push @{ $count{$element} > 1 ? \@intersection : \@difference }, $element;
+               }
+
+Note that this is the I<symmetric difference>, that is, all elements
+in either A or in B but not in both.  Think of it as an xor operation.
+
+=head2 How do I test whether two arrays or hashes are equal?
+
+With Perl 5.10 and later, the smart match operator can give you the answer
+with the least amount of work:
+
+       use 5.010;
+
+       if( @array1 ~~ @array2 )
+               {
+               say "The arrays are the same";
+               }
+
+       if( %hash1 ~~ %hash2 ) # doesn't check values!
+               {
+               say "The hash keys are the same";
+               }
+
+The following code works for single-level arrays.  It uses a
+stringwise comparison, and does not distinguish defined versus
+undefined empty strings.  Modify if you have other needs.
+
+       $are_equal = compare_arrays(\@frogs, \@toads);
+
+       sub compare_arrays {
+               my ($first, $second) = @_;
+               no warnings;  # silence spurious -w undef complaints
+               return 0 unless @$first == @$second;
+               for (my $i = 0; $i < @$first; $i++) {
+                       return 0 if $first->[$i] ne $second->[$i];
+                       }
+               return 1;
+               }
+
+For multilevel structures, you may wish to use an approach more
+like this one.  It uses the CPAN module C<FreezeThaw>:
+
+       use FreezeThaw qw(cmpStr);
+       @a = @b = ( "this", "that", [ "more", "stuff" ] );
+
+       printf "a and b contain %s arrays\n",
+               cmpStr(\@a, \@b) == 0
+               ? "the same"
+               : "different";
+
+This approach also works for comparing hashes.  Here we'll demonstrate
+two different answers:
+
+       use FreezeThaw qw(cmpStr cmpStrHard);
+
+       %a = %b = ( "this" => "that", "extra" => [ "more", "stuff" ] );
+       $a{EXTRA} = \%b;
+       $b{EXTRA} = \%a;
+
+       printf "a and b contain %s hashes\n",
+       cmpStr(\%a, \%b) == 0 ? "the same" : "different";
+
+       printf "a and b contain %s hashes\n",
+       cmpStrHard(\%a, \%b) == 0 ? "the same" : "different";
+
+
+The first reports that both those the hashes contain the same data,
+while the second reports that they do not.  Which you prefer is left as
+an exercise to the reader.
 
 =head2 How do I find the first array element for which a condition is true?
 
-You can use this if you care about the index:
+To find the first array element which satisfies a condition, you can
+use the C<first()> function in the C<List::Util> module, which comes
+with Perl 5.8. This example finds the first element that contains
+"Perl".
 
-    for ($i=0; $i < @array; $i++) {
-        if ($array[$i] eq "Waldo") {
-           $found_index = $i;
-            last;
-        }
-    }
+       use List::Util qw(first);
+
+       my $element = first { /Perl/ } @array;
+
+If you cannot use C<List::Util>, you can make your own loop to do the
+same thing.  Once you find the element, you stop the loop with last.
+
+       my $found;
+       foreach ( @array ) {
+               if( /Perl/ ) { $found = $_; last }
+               }
+
+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.
 
-Now C<$found_index> has what you want.
+       my( $found, $index ) = ( undef, -1 );
+       for( $i = 0; $i < @array; $i++ ) {
+               if( $array[$i] =~ /Perl/ ) {
+                       $found = $array[$i];
+                       $index = $i;
+                       last;
+                       }
+               }
 
 =head2 How do I handle linked lists?
 
 In general, you usually don't need a linked list in Perl, since with
-regular arrays, you can push and pop or shift and unshift at either end,
-or you can use splice to add and/or remove arbitrary number of elements at
-arbitrary points.  Both pop and shift are both O(1) operations on perl's
-dynamic arrays.  In the absence of shifts and pops, push in general
-needs to reallocate on the order every log(N) times, and unshift will
-need to copy pointers each time.
+regular arrays, you can push and pop or shift and unshift at either
+end, or you can use splice to add and/or remove arbitrary number of
+elements at arbitrary points.  Both pop and shift are O(1)
+operations on Perl's dynamic arrays.  In the absence of shifts and
+pops, push in general needs to reallocate on the order every log(N)
+times, and unshift will need to copy pointers each time.
 
 If you really, really wanted, you could use structures as described in
-L<perldsc> or L<perltoot> and do just what the algorithm book tells you
-to do.
+L<perldsc> or L<perltoot> and do just what the algorithm book tells
+you to do.  For example, imagine a list node like this:
+
+       $node = {
+               VALUE => 42,
+               LINK  => undef,
+               };
+
+You could walk the list this way:
+
+       print "List: ";
+       for ($node = $head;  $node; $node = $node->{LINK}) {
+               print $node->{VALUE}, " ";
+               }
+       print "\n";
+
+You could add to the list this way:
+
+       my ($head, $tail);
+       $tail = append($head, 1);       # grow a new head
+       for $value ( 2 .. 10 ) {
+               $tail = append($tail, $value);
+               }
+
+       sub append {
+               my($list, $value) = @_;
+               my $node = { VALUE => $value };
+               if ($list) {
+                       $node->{LINK} = $list->{LINK};
+                       $list->{LINK} = $node;
+                       }
+               else {
+                       $_[0] = $node;      # replace caller's version
+                       }
+               return $node;
+               }
+
+But again, Perl's built-in are virtually always good enough.
 
 =head2 How do I handle circular lists?
+X<circular> X<array> X<Tie::Cycle> X<Array::Iterator::Circular>
+X<cycle> X<modulus>
+
+(contributed by brian d foy)
+
+If you want to cycle through an array endlessy, you can increment the
+index modulo the number of elements in the array:
+
+       my @array = qw( a b c );
+       my $i = 0;
+
+       while( 1 ) {
+               print $array[ $i++ % @array ], "\n";
+               last if $i > 20;
+               }
+
+You can also use C<Tie::Cycle> to use a scalar that always has the
+next element of the circular array:
 
-Circular lists could be handled in the traditional fashion with linked
-lists, or you could just do something like this with an array:
+       use Tie::Cycle;
 
-    unshift(@array, pop(@array));  # the last shall be first
-    push(@array, shift(@array));   # and vice versa
+       tie my $cycle, 'Tie::Cycle', [ qw( FFFFFF 000000 FFFF00 ) ];
+
+       print $cycle; # FFFFFF
+       print $cycle; # 000000
+       print $cycle; # FFFF00
+
+The C<Array::Iterator::Circular> creates an iterator object for
+circular arrays:
+
+       use Array::Iterator::Circular;
+
+       my $color_iterator = Array::Iterator::Circular->new(
+               qw(red green blue orange)
+               );
+
+       foreach ( 1 .. 20 ) {
+               print $color_iterator->next, "\n";
+               }
 
 =head2 How do I shuffle an array randomly?
 
-Use this:
-
-    # fisher_yates_shuffle( \@array ) : 
-    # generate a random permutation of @array in place
-    sub fisher_yates_shuffle {
-        my $array = shift;
-        my $i;
-        for ($i = @$array; --$i; ) {
-            my $j = int rand ($i+1);
-            next if $i == $j;
-            @$array[$i,$j] = @$array[$j,$i];
-        }
-    }
+If you either have Perl 5.8.0 or later installed, or if you have
+Scalar-List-Utils 1.03 or later installed, you can say:
 
-    fisher_yates_shuffle( \@array );    # permutes @array in place
+       use List::Util 'shuffle';
 
-You've probably seen shuffling algorithms that works using splice,
-randomly picking another element to swap the current element with:
+       @shuffled = shuffle(@list);
 
-    srand;
-    @new = ();
-    @old = 1 .. 10;  # just a demo
-    while (@old) {
-       push(@new, splice(@old, rand @old, 1));
-    }
+If not, you can use a Fisher-Yates shuffle.
+
+       sub fisher_yates_shuffle {
+               my $deck = shift;  # $deck is a reference to an array
+               return unless @$deck; # must not be empty!
+
+               my $i = @$deck;
+               while (--$i) {
+                       my $j = int rand ($i+1);
+                       @$deck[$i,$j] = @$deck[$j,$i];
+                       }
+       }
 
-This is bad because splice is already O(N), and since you do it N times,
-you just invented a quadratic algorithm; that is, O(N**2).  This does
-not scale, although Perl is so efficient that you probably won't notice
-this until you have rather largish arrays.
+       # shuffle my mpeg collection
+       #
+       my @mpeg = <audio/*/*.mp3>;
+       fisher_yates_shuffle( \@mpeg );    # randomize @mpeg in place
+       print @mpeg;
+
+Note that the above implementation shuffles an array in place,
+unlike the C<List::Util::shuffle()> which takes a list and returns
+a new shuffled list.
+
+You've probably seen shuffling algorithms that work using splice,
+randomly picking another element to swap the current element with
+
+       srand;
+       @new = ();
+       @old = 1 .. 10;  # just a demo
+       while (@old) {
+               push(@new, splice(@old, rand @old, 1));
+               }
+
+This is bad because splice is already O(N), and since you do it N
+times, you just invented a quadratic algorithm; that is, O(N**2).
+This does not scale, although Perl is so efficient that you probably
+won't notice this until you have rather largish arrays.
 
 =head2 How do I process/modify each element of an array?
 
 Use C<for>/C<foreach>:
 
-    for (@lines) {
-       s/foo/bar/;     # change that word
-       y/XZ/ZX/;       # swap those letters
-    }
+       for (@lines) {
+               s/foo/bar/;     # change that word
+               tr/XZ/ZX/;      # swap those letters
+               }
 
 Here's another; let's compute spherical volumes:
 
-    for (@volumes = @radii) {   # @volumes has changed parts
-       $_ **= 3;
-       $_ *= (4/3) * 3.14159;  # this will be constant folded
-    }
+       for (@volumes = @radii) {   # @volumes has changed parts
+               $_ **= 3;
+               $_ *= (4/3) * 3.14159;  # this will be constant folded
+               }
 
-If you want to do the same thing to modify the values of the hash,
-you may not use the C<values> function, oddly enough.  You need a slice:
+which can also be done with C<map()> which is made to transform
+one list into another:
 
-    for $orbit ( @orbits{keys %orbits} ) {
-       ($orbit **= 3) *= (4/3) * 3.14159; 
-    }
+       @volumes = map {$_ ** 3 * (4/3) * 3.14159} @radii;
+
+If you want to do the same thing to modify the values of the
+hash, you can use the C<values> function.  As of Perl 5.6
+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;
+               }
+
+Prior to perl 5.6 C<values> returned copies of the values,
+so older perl code often contains constructions such as
+C<@orbits{keys %orbits}> instead of C<values %orbits> where
+the hash is to be modified.
 
 =head2 How do I select a random element from an array?
 
-Use the rand() function (see L<perlfunc/rand>):
+Use the C<rand()> function (see L<perlfunc/rand>):
 
-    # at the top of the program:
-    srand;                     # not needed for 5.004 and later
+       $index   = rand @array;
+       $element = $array[$index];
 
-    # then later on
-    $index   = rand @array;
-    $element = $array[$index];
+Or, simply:
 
-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.
+       my $element = $array[ rand @array ];
 
 =head2 How do I permute N elements of a list?
+X<List::Permuter> X<permute> X<Algorithm::Loops> X<Knuth>
+X<The Art of Computer Programming> X<Fischer-Krause>
 
-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 should work on any list:
-
-    #!/usr/bin/perl -n
-    # tsc-permute: permute each word of input
-    permute([split], []);
-    sub permute {
-        my @items = @{ $_[0] };
-        my @perms = @{ $_[1] };
-        unless (@items) {
-            print "@perms\n";
-       } else {
-            my(@newitems,@newperms,$i);
-            foreach $i (0 .. $#items) {
-                @newitems = @items;
-                @newperms = @perms;
-                unshift(@newperms, splice(@newitems, $i, 1));
-                permute([@newitems], [@newperms]);
-           }
+Use the C<List::Permutor> module on CPAN. If the list is actually an
+array, try the C<Algorithm::Permute> module (also on CPAN). It's
+written in XS code and is very efficient:
+
+       use Algorithm::Permute;
+
+       my @array = 'a'..'d';
+       my $p_iterator = Algorithm::Permute->new ( \@array );
+
+       while (my @perm = $p_iterator->next) {
+          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
+C<permute()> function is discussed in Volume 4 (still unpublished) of
+Knuth's I<The Art of Computer Programming> and will work on any list:
+
+       #!/usr/bin/perl -n
+       # Fischer-Krause ordered permutation generator
+
+       sub permute (&@) {
+               my $code = shift;
+               my @idx = 0..$#_;
+               while ( $code->(@_[@idx]) ) {
+                       my $p = $#idx;
+                       --$p while $idx[$p-1] > $idx[$p];
+                       my $q = $p or return;
+                       push @idx, reverse splice @idx, $p;
+                       ++$q while $idx[$p-1] > $idx[$q];
+                       @idx[$p-1,$q]=@idx[$q,$p-1];
+               }
        }
-    }
+
+       permute { print "@_\n" } split;
+
+The C<Algorithm::Loops> module also provides the C<NextPermute> and
+C<NextPermuteNum> functions which efficiently find all unique permutations
+of an array, even if it contains duplicate values, modifying it in-place:
+if its elements are in reverse-sorted order then the array is reversed,
+making it sorted, and it returns false; otherwise the next
+permutation is returned.
+
+C<NextPermute> uses string order and C<NextPermuteNum> numeric order, so
+you can enumerate all the permutations of C<0..9> like this:
+
+       use Algorithm::Loops qw(NextPermuteNum);
+
+    my @list= 0..9;
+    do { print "@list\n" } while NextPermuteNum @list;
 
 =head2 How do I sort an array by (anything)?
 
 Supply a comparison function to sort() (described in L<perlfunc/sort>):
 
-    @list = sort { $a <=> $b } @list;
+       @list = sort { $a <=> $b } @list;
 
 The default sort function is cmp, string comparison, which would
-sort C<(1, 2, 10)> into C<(1, 10, 2)>.  C<E<lt>=E<gt>>, used above, is
+sort C<(1, 2, 10)> into C<(1, 10, 2)>.  C<< <=> >>, used above, is
 the numerical comparison operator.
 
 If you have a complicated function needed to pull out the part you
@@ -933,169 +1755,408 @@ same element.  Here's an example of how to pull out the first word
 after the first number on each item, and then sort those words
 case-insensitively.
 
-    @idx = ();
-    for (@data) {
-       ($item) = /\d+\s*(\S+)/;
-       push @idx, uc($item);
-    }
-    @sorted = @data[ sort { $idx[$a] cmp $idx[$b] } 0 .. $#idx ];
+       @idx = ();
+       for (@data) {
+               ($item) = /\d+\s*(\S+)/;
+               push @idx, uc($item);
+           }
+       @sorted = @data[ sort { $idx[$a] cmp $idx[$b] } 0 .. $#idx ];
 
-Which could also be written this way, using a trick
+which could also be written this way, using a trick
 that's come to be known as the Schwartzian Transform:
 
-    @sorted = map  { $_->[0] }
-             sort { $a->[1] cmp $b->[1] }
-             map  { [ $_, uc((/\d+\s*(\S+)/ )[0] ] } @data;
+       @sorted = map  { $_->[0] }
+               sort { $a->[1] cmp $b->[1] }
+               map  { [ $_, uc( (/\d+\s*(\S+)/)[0]) ] } @data;
 
 If you need to sort on several fields, the following paradigm is useful.
 
-    @sorted = sort { field1($a) <=> field1($b) ||
-                     field2($a) cmp field2($b) ||
-                     field3($a) cmp field3($b)
-                   }     @data;
+       @sorted = sort {
+               field1($a) <=> field1($b) ||
+               field2($a) cmp field2($b) ||
+               field3($a) cmp field3($b)
+               } @data;
 
 This can be conveniently combined with precalculation of keys as given
 above.
 
-See http://www.perl.com/CPAN/doc/FMTEYEWTK/sort.html for more about
-this approach.
+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.
 
-See also the question below on sorting hashes.
+See also the question later in L<perlfaq4> on sorting hashes.
 
 =head2 How do I manipulate arrays of bits?
 
-Use pack() and unpack(), or else vec() and the bitwise operations.
-
-For example, this sets $vec to have bit N set if $ints[N] was set:
-
-    $vec = '';
-    foreach(@ints) { vec($vec,$_,1) = 1 }
-
-And here's how, given a vector in $vec, you can
-get those bits into your @ints array:
-
-    sub bitvec_to_list {
-       my $vec = shift;
-       my @ints;
-       # Find null-byte density then select best algorithm
-       if ($vec =~ tr/\0// / length $vec > 0.95) {
-           use integer;
-           my $i;
-           # This method is faster with mostly null-bytes
-           while($vec =~ /[^\0]/g ) {
-               $i = -9 + 8 * pos $vec;
-               push @ints, $i if vec($vec, ++$i, 1);
-               push @ints, $i if vec($vec, ++$i, 1);
-               push @ints, $i if vec($vec, ++$i, 1);
-               push @ints, $i if vec($vec, ++$i, 1);
-               push @ints, $i if vec($vec, ++$i, 1);
-               push @ints, $i if vec($vec, ++$i, 1);
-               push @ints, $i if vec($vec, ++$i, 1);
-               push @ints, $i if vec($vec, ++$i, 1);
-           }
-       } else {
-           # This method is a fast general algorithm
-           use integer;
-           my $bits = unpack "b*", $vec;
-           push @ints, 0 if $bits =~ s/^(\d)// && $1;
-           push @ints, pos $bits while($bits =~ /1/g);
-       }
-       return \@ints;
-    }
+Use C<pack()> and C<unpack()>, or else C<vec()> and the bitwise
+operations.
+
+For example, you don't have to store individual bits in an array
+(which would mean that you're wasting a lot of space). To convert an
+array of bits to a string, use C<vec()> to set the right bits. This
+sets C<$vec> to have bit N set only if C<$ints[N]> was set:
+
+       @ints = (...); # array of bits, e.g. ( 1, 0, 0, 1, 1, 0 ... )
+       $vec = '';
+       foreach( 0 .. $#ints ) {
+               vec($vec,$_,1) = 1 if $ints[$_];
+               }
+
+The string C<$vec> only takes up as many bits as it needs. For
+instance, if you had 16 entries in C<@ints>, C<$vec> only needs two
+bytes to store them (not counting the scalar variable overhead).
+
+Here's how, given a vector in C<$vec>, you can get those bits into
+your C<@ints> array:
+
+       sub bitvec_to_list {
+               my $vec = shift;
+               my @ints;
+               # Find null-byte density then select best algorithm
+               if ($vec =~ tr/\0// / length $vec > 0.95) {
+                       use integer;
+                       my $i;
+
+                       # This method is faster with mostly null-bytes
+                       while($vec =~ /[^\0]/g ) {
+                               $i = -9 + 8 * pos $vec;
+                               push @ints, $i if vec($vec, ++$i, 1);
+                               push @ints, $i if vec($vec, ++$i, 1);
+                               push @ints, $i if vec($vec, ++$i, 1);
+                               push @ints, $i if vec($vec, ++$i, 1);
+                               push @ints, $i if vec($vec, ++$i, 1);
+                               push @ints, $i if vec($vec, ++$i, 1);
+                               push @ints, $i if vec($vec, ++$i, 1);
+                               push @ints, $i if vec($vec, ++$i, 1);
+                               }
+                       }
+               else {
+                       # This method is a fast general algorithm
+                       use integer;
+                       my $bits = unpack "b*", $vec;
+                       push @ints, 0 if $bits =~ s/^(\d)// && $1;
+                       push @ints, pos $bits while($bits =~ /1/g);
+                       }
+
+               return \@ints;
+               }
 
 This method gets faster the more sparse the bit vector is.
 (Courtesy of Tim Bunce and Winfried Koenig.)
 
+You can make the while loop a lot shorter with this suggestion
+from Benjamin Goldberg:
+
+       while($vec =~ /[^\0]+/g ) {
+               push @ints, grep vec($vec, $_, 1), $-[0] * 8 .. $+[0] * 8;
+               }
+
+Or use the CPAN module C<Bit::Vector>:
+
+       $vector = Bit::Vector->new($num_of_bits);
+       $vector->Index_List_Store(@ints);
+       @ints = $vector->Index_List_Read();
+
+C<Bit::Vector> provides efficient methods for bit vector, sets of
+small integers 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 ",
+       unpack("N", $vector), "\n";
+       $is_set = vec($vector, 23, 1);
+       print "Its 23rd bit is ", $is_set ? "set" : "clear", ".\n";
+       pvec($vector);
+
+       set_vec(1,1,1);
+       set_vec(3,1,1);
+       set_vec(23,1,1);
+
+       set_vec(3,1,3);
+       set_vec(3,2,3);
+       set_vec(3,4,3);
+       set_vec(3,4,7);
+       set_vec(3,8,3);
+       set_vec(3,8,7);
+
+       set_vec(0,32,17);
+       set_vec(1,32,17);
+
+       sub set_vec {
+               my ($offset, $width, $value) = @_;
+               my $vector = '';
+               vec($vector, $offset, $width) = $value;
+               print "offset=$offset width=$width value=$value\n";
+               pvec($vector);
+               }
+
+       sub pvec {
+               my $vector = shift;
+               my $bits = unpack("b*", $vector);
+               my $i = 0;
+               my $BASE = 8;
+
+               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?
 
-See L<perlfunc/defined> in the 5.004 release or later of Perl.
+The short story is that you should probably only use defined on scalars or
+functions, not on aggregates (arrays and hashes).  See L<perlfunc/defined>
+in the 5.004 release or later of Perl for more detail.
 
 =head1 Data: Hashes (Associative Arrays)
 
 =head2 How do I process an entire hash?
 
-Use the each() function (see L<perlfunc/each>) if you don't care
-whether it's sorted:
+(contributed by brian d foy)
+
+There are a couple of ways that you can process an entire hash. You
+can get a list of keys, then go through each key, or grab a one
+key-value pair at a time.
+
+To go through all of the keys, use the C<keys> function. This extracts
+all of the keys of the hash and gives them back to you as a list. You
+can then get the value through the particular key you're processing:
+
+       foreach my $key ( keys %hash ) {
+               my $value = $hash{$key}
+               ...
+               }
+
+Once you have the list of keys, you can process that list before you
+process the hash elements. For instance, you can sort the keys so you
+can process them in lexical order:
+
+       foreach my $key ( sort keys %hash ) {
+               my $value = $hash{$key}
+               ...
+               }
+
+Or, you might want to only process some of the items. If you only want
+to deal with the keys that start with C<text:>, you can select just
+those using C<grep>:
+
+       foreach my $key ( grep /^text:/, keys %hash ) {
+               my $value = $hash{$key}
+               ...
+               }
+
+If the hash is very large, you might not want to create a long list of
+keys. To save some memory, you can grab one key-value pair at a time using
+C<each()>, which returns a pair you haven't seen yet:
+
+       while( my( $key, $value ) = each( %hash ) ) {
+               ...
+               }
+
+The C<each> operator returns the pairs in apparently random order, so if
+ordering matters to you, you'll have to stick with the C<keys> method.
+
+The C<each()> operator can be a bit tricky though. You can't add or
+delete keys of the hash while you're using it without possibly
+skipping or re-processing some pairs after Perl internally rehashes
+all of the elements. Additionally, a hash has only one iterator, so if
+you use C<keys>, C<values>, or C<each> on the same hash, you can reset
+the iterator and mess up your processing. See the C<each> entry in
+L<perlfunc> for more details.
+
+=head2 How do I merge two hashes?
+X<hash> X<merge> X<slice, hash>
+
+(contributed by brian d foy)
+
+Before you decide to merge two hashes, you have to decide what to do
+if both hashes contain keys that are the same and if you want to leave
+the original hashes as they were.
+
+If you want to preserve the original hashes, copy one hash (C<%hash1>)
+to a new hash (C<%new_hash>), then add the keys from the other hash
+(C<%hash2> to the new hash. Checking that the key already exists in
+C<%new_hash> gives you a chance to decide what to do with the
+duplicates:
+
+       my %new_hash = %hash1; # make a copy; leave %hash1 alone
+
+       foreach my $key2 ( keys %hash2 )
+               {
+               if( exists $new_hash{$key2} )
+                       {
+                       warn "Key [$key2] is in both hashes!";
+                       # handle the duplicate (perhaps only warning)
+                       ...
+                       next;
+                       }
+               else
+                       {
+                       $new_hash{$key2} = $hash2{$key2};
+                       }
+               }
+
+If you don't want to create a new hash, you can still use this looping
+technique; just change the C<%new_hash> to C<%hash1>.
+
+       foreach my $key2 ( keys %hash2 )
+               {
+               if( exists $hash1{$key2} )
+                       {
+                       warn "Key [$key2] is in both hashes!";
+                       # handle the duplicate (perhaps only warning)
+                       ...
+                       next;
+                       }
+               else
+                       {
+                       $hash1{$key2} = $hash2{$key2};
+                       }
+               }
+
+If you don't care that one hash overwrites keys and values from the other, you
+could just use a hash slice to add one hash to another. In this case, values
+from C<%hash2> replace values from C<%hash1> when they have keys in common:
+
+       @hash1{ keys %hash2 } = values %hash2;
 
-    while ( ($key, $value) = each %hash) {
-       print "$key = $value\n";
-    }
+=head2 What happens if I add or remove keys from a hash while iterating over it?
 
-If you want it sorted, you'll have to use foreach() on the result of
-sorting the keys as shown in an earlier question.
+(contributed by brian d foy)
 
-=head2 What happens if I add or remove keys from a hash while iterating over it?
+The easy answer is "Don't do that!"
 
-Don't do that.
+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?
 
 Create a reverse hash:
 
-    %by_value = reverse %by_key;
-    $key = $by_value{$value};
+       %by_value = reverse %by_key;
+       $key = $by_value{$value};
 
 That's not particularly efficient.  It would be more space-efficient
 to use:
 
-    while (($key, $value) = each %by_key) {
-       $by_value{$value} = $key;
-    }
+       while (($key, $value) = each %by_key) {
+               $by_value{$value} = $key;
+           }
 
-If your hash could have repeated values, the methods above will only
-find one of the associated keys.   This may or may not worry you.
+If your hash could have repeated values, the methods above will only find
+one of the associated keys.   This may or may not worry you.  If it does
+worry you, you can always reverse the hash into a hash of arrays instead:
+
+       while (($key, $value) = each %by_key) {
+                push @{$key_list_by_value{$value}}, $key;
+               }
 
 =head2 How can I know how many entries are in a hash?
 
-If you mean how many keys, then all you have to do is
-take the scalar sense of the keys() function:
+(contributed by brian d foy)
+
+This is very similar to "How do I process an entire hash?", also in
+L<perlfaq4>, but a bit simpler in the common cases.
+
+You can use the C<keys()> built-in function in scalar context to find out
+have many entries you have in a hash:
+
+       my $key_count = keys %hash; # must be scalar context!
+       
+If you want to find out how many entries have a defined value, that's
+a bit different. You have to check each value. A C<grep> is handy: 
+
+       my $defined_value_count = grep { defined } values %hash;
 
-    $num_keys = scalar keys %hash;
+You can use that same structure to count the entries any way that
+you like. If you want the count of the keys with vowels in them,
+you just test for that instead:
 
-In void context it just resets the iterator, which is faster
-for tied hashes.
+       my $vowel_count = grep { /[aeiou]/ } keys %hash;
+       
+The C<grep> in scalar context returns the count. If you want the list
+of matching items, just use it in list context instead:
+
+       my @defined_values = grep { defined } values %hash;
+
+The C<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 C<each()>.
 
 =head2 How do I sort a hash (optionally by value instead of key)?
 
-Internally, hashes are stored in a way that prevents you from imposing
-an order on key-value pairs.  Instead, you have to sort a list of the
-keys or values:
+(contributed by brian d foy)
+
+To sort a hash, start with the keys. In this example, we give the list of
+keys to the sort function which then compares them ASCIIbetically (which
+might be affected by your locale settings). The output list has the keys
+in ASCIIbetical order. Once we have the keys, we can go through them to
+create a report which lists the keys in ASCIIbetical order.
+
+       my @keys = sort { $a cmp $b } keys %hash;
+
+       foreach my $key ( @keys )
+               {
+               printf "%-20s %6d\n", $key, $hash{$key};
+               }
+
+We could get more fancy in the C<sort()> block though. Instead of
+comparing the keys, we can compute a value with them and use that
+value as the comparison.
+
+For instance, to make our report order case-insensitive, we use
+the C<\L> sequence in a double-quoted string to make everything
+lowercase. The C<sort()> block then compares the lowercased
+values to determine in which order to put the keys.
+
+       my @keys = sort { "\L$a" cmp "\L$b" } keys %hash;
+
+Note: if the computation is expensive or the hash has many elements,
+you may want to look at the Schwartzian Transform to cache the
+computation results.
+
+If we want to sort by the hash value instead, we use the hash key
+to look it up. We still get out a list of keys, but this time they
+are ordered by their value.
 
-    @keys = sort keys %hash;   # sorted by key
-    @keys = sort {
-                   $hash{$a} cmp $hash{$b}
-           } keys %hash;       # and by value
+       my @keys = sort { $hash{$a} <=> $hash{$b} } keys %hash;
 
-Here we'll do a reverse numeric sort by value, and if two keys are
-identical, sort by length of key, and if that fails, by straight ASCII
-comparison of the keys (well, possibly modified by your locale -- see
-L<perllocale>).
+From there we can get more complex. If the hash values are the same,
+we can provide a secondary sort on the hash key.
 
-    @keys = sort {
-               $hash{$b} <=> $hash{$a}
-                         ||
-               length($b) <=> length($a)
-                         ||
-                     $a cmp $b
-    } keys %hash;
+       my @keys = sort {
+               $hash{$a} <=> $hash{$b}
+                       or
+               "\L$a" cmp "\L$b"
+               } keys %hash;
 
 =head2 How can I always keep my hash sorted?
+X<hash tie sort DB_File Tie::IxHash>
 
-You can look into using the DB_File module and tie() using the
-$DB_BTREE hash bindings as documented in L<DB_File/"In Memory Databases">.
-The Tie::IxHash module from CPAN might also be instructive.
+You can look into using the C<DB_File> module and C<tie()> using the
+C<$DB_BTREE> hash bindings as documented in L<DB_File/"In Memory
+Databases">. The C<Tie::IxHash> module from CPAN might also be
+instructive. Although this does keep your hash sorted, you might not
+like the slow down you suffer from the tie interface. Are you sure you
+need to do this? :)
 
 =head2 What's the difference between "delete" and "undef" with hashes?
 
-Hashes are pairs of scalars: the first is the key, the second is the
-value.  The key will be coerced to a string, although the value can be
-any kind of scalar: string, number, or reference.  If a key C<$key> is
-present in the array, C<exists($key)> will return true.  The value for
-a given key can be C<undef>, in which case C<$array{$key}> will be
-C<undef> while C<$exists{$key}> will return true.  This corresponds to
-(C<$key>, C<undef>) being in the hash.
+Hashes contain pairs of scalars: the first is the key, the
+second is the value.  The key will be coerced to a string,
+although the value can be any kind of scalar: string,
+number, or reference.  If a key C<$key> is present in
+%hash, C<exists($hash{$key})> will return true.  The value
+for a given key can be C<undef>, in which case
+C<$hash{$key}> will be C<undef> while C<exists $hash{$key}>
+will return true.  This corresponds to (C<$key>, C<undef>)
+being in the hash.
 
-Pictures help...  here's the C<%ary> table:
+Pictures help...  here's the C<%hash> table:
 
          keys  values
        +------+------+
@@ -1107,16 +2168,16 @@ Pictures help...  here's the C<%ary> table:
 
 And these conditions hold
 
-       $ary{'a'}                       is true
-       $ary{'d'}                       is false
-       defined $ary{'d'}               is true
-       defined $ary{'a'}               is true
-       exists $ary{'a'}                is true (perl5 only)
-       grep ($_ eq 'a', keys %ary)     is true
+       $hash{'a'}                       is true
+       $hash{'d'}                       is false
+       defined $hash{'d'}               is true
+       defined $hash{'a'}               is true
+       exists $hash{'a'}                is true (Perl 5 only)
+       grep ($_ eq 'a', keys %hash)     is true
 
 If you now say
 
-       undef $ary{'a'}
+       undef $hash{'a'}
 
 your table now reads:
 
@@ -1131,18 +2192,18 @@ your table now reads:
 
 and these conditions now hold; changes in caps:
 
-       $ary{'a'}                       is FALSE
-       $ary{'d'}                       is false
-       defined $ary{'d'}               is true
-       defined $ary{'a'}               is FALSE
-       exists $ary{'a'}                is true (perl5 only)
-       grep ($_ eq 'a', keys %ary)     is true
+       $hash{'a'}                       is FALSE
+       $hash{'d'}                       is false
+       defined $hash{'d'}               is true
+       defined $hash{'a'}               is FALSE
+       exists $hash{'a'}                is true (Perl 5 only)
+       grep ($_ eq 'a', keys %hash)     is true
 
 Notice the last two: you have an undef value, but a defined key!
 
 Now, consider this:
 
-       delete $ary{'a'}
+       delete $hash{'a'}
 
 your table now reads:
 
@@ -1155,56 +2216,61 @@ your table now reads:
 
 and these conditions now hold; changes in caps:
 
-       $ary{'a'}                       is false
-       $ary{'d'}                       is false
-       defined $ary{'d'}               is true
-       defined $ary{'a'}               is false
-       exists $ary{'a'}                is FALSE (perl5 only)
-       grep ($_ eq 'a', keys %ary)     is FALSE
+       $hash{'a'}                       is false
+       $hash{'d'}                       is false
+       defined $hash{'d'}               is true
+       defined $hash{'a'}               is false
+       exists $hash{'a'}                is FALSE (Perl 5 only)
+       grep ($_ eq 'a', keys %hash)     is FALSE
 
 See, the whole entry is gone!
 
 =head2 Why don't my tied hashes make the defined/exists distinction?
 
-They may or may not implement the EXISTS() and DEFINED() methods
-differently.  For example, there isn't the concept of undef with hashes
-that are tied to DBM* files. This means the true/false tables above
-will give different results when used on such a hash.  It also means
-that exists and defined do the same thing with a DBM* file, and what
-they end up doing is not what they do with ordinary hashes.
+This depends on the tied hash's implementation of EXISTS().
+For example, there isn't the concept of undef with hashes
+that are tied to DBM* files. It also means that exists() and
+defined() do the same thing with a DBM* file, and what they
+end up doing is not what they do with ordinary hashes.
 
 =head2 How do I reset an each() operation part-way through?
 
-Using C<keys %hash> in scalar context returns the number of keys in
-the hash I<and> resets the iterator associated with the hash.  You may
-need to do this if you use C<last> to exit a loop early so that when you
-re-enter it, the hash iterator has been reset.
+(contributed by brian d foy)
+
+You can use the C<keys> or C<values> functions to reset C<each>. To
+simply reset the iterator used by C<each> without doing anything else,
+use one of them in void context:
+
+       keys %hash; # resets iterator, nothing else.
+       values %hash; # resets iterator, nothing else.
+
+See the documentation for C<each> in L<perlfunc>.
 
 =head2 How can I get the unique keys from two hashes?
 
-First you extract the keys from the hashes into arrays, and then solve
-the uniquifying the array problem described above.  For example:
+First you extract the keys from the hashes into lists, then solve
+the "removing duplicates" problem described above.  For example:
 
-    %seen = ();
-    for $element (keys(%foo), keys(%bar)) {
-       $seen{$element}++;
-    }
-    @uniq = keys %seen;
+       %seen = ();
+       for $element (keys(%foo), keys(%bar)) {
+               $seen{$element}++;
+               }
+       @uniq = keys %seen;
 
 Or more succinctly:
 
-    @uniq = keys %{{%foo,%bar}};
+       @uniq = keys %{{%foo,%bar}};
 
 Or if you really want to save space:
 
-    %seen = ();
-    while (defined ($key = each %foo)) {
-        $seen{$key}++;
-    }
-    while (defined ($key = each %bar)) {
-        $seen{$key}++;
-    }
-    @uniq = keys %seen;
+       %seen = ();
+       while (defined ($key = each %foo)) {
+               $seen{$key}++;
+       }
+       while (defined ($key = each %bar)) {
+               $seen{$key}++;
+       }
+       @uniq = keys %seen;
 
 =head2 How can I store a multidimensional array in a DBM file?
 
@@ -1214,60 +2280,118 @@ it on top of either DB_File or GDBM_File.
 
 =head2 How can I make my hash remember the order I put elements into it?
 
-Use the Tie::IxHash from CPAN.
+Use the C<Tie::IxHash> from CPAN.
 
-    use Tie::IxHash;
-    tie(%myhash, Tie::IxHash);
-    for ($i=0; $i<20; $i++) {
-        $myhash{$i} = 2*$i;
-    }
-    @keys = keys %myhash;
-    # @keys = (0,1,2,3,...)
+       use Tie::IxHash;
+
+       tie my %myhash, 'Tie::IxHash';
+
+       for (my $i=0; $i<20; $i++) {
+               $myhash{$i} = 2*$i;
+               }
+
+       my @keys = keys %myhash;
+       # @keys = (0,1,2,3,...)
 
 =head2 Why does passing a subroutine an undefined element in a hash create it?
 
-If you say something like:
+(contributed by brian d foy)
+
+Are you using a really old version of Perl?
+
+Normally, accessing a hash key's value for a nonexistent key will
+I<not> create the key.
+
+       my %hash  = ();
+       my $value = $hash{ 'foo' };
+       print "This won't print\n" if exists $hash{ 'foo' };
+
+Passing C<$hash{ 'foo' }> to a subroutine used to be a special case, though.
+Since you could assign directly to C<$_[0]>, Perl had to be ready to
+make that assignment so it created the hash key ahead of time:
 
-    somefunc($hash{"nonesuch key here"});
+    my_sub( $hash{ 'foo' } );
+       print "This will print before 5.004\n" if exists $hash{ 'foo' };
 
-Then that element "autovivifies"; that is, it springs into existence
-whether you store something there or not.  That's because functions
-get scalars passed in by reference.  If somefunc() modifies C<$_[0]>,
-it has to be ready to write it back into the caller's version.
+       sub my_sub {
+               # $_[0] = 'bar'; # create hash key in case you do this
+               1;
+               }
 
-This has been fixed as of perl5.004.
+Since Perl 5.004, however, this situation is a special case and Perl
+creates the hash key only when you make the assignment:
 
-Normally, merely accessing a key's value for a nonexistent key does
-I<not> cause that key to be forever there.  This is different than
-awk's behavior.
+    my_sub( $hash{ 'foo' } );
+       print "This will print, even after 5.004\n" if exists $hash{ 'foo' };
+
+       sub my_sub {
+               $_[0] = 'bar';
+               }
+
+However, if you want the old behavior (and think carefully about that
+because it's a weird side effect), you can pass a hash slice instead.
+Perl 5.004 didn't make this a special case:
+
+       my_sub( @hash{ qw/foo/ } );
 
 =head2 How can I make the Perl equivalent of a C structure/C++ class/hash or array of hashes or arrays?
 
-Use references (documented in L<perlref>).  Examples of complex data
-structures are given in L<perldsc> and L<perllol>.  Examples of
-structures and object-oriented classes are in L<perltoot>.
+Usually a hash ref, perhaps like this:
+
+       $record = {
+               NAME   => "Jason",
+               EMPNO  => 132,
+               TITLE  => "deputy peon",
+               AGE    => 23,
+               SALARY => 37_000,
+               PALS   => [ "Norbert", "Rhys", "Phineas"],
+       };
+
+References are documented in L<perlref> and the upcoming L<perlreftut>.
+Examples of complex data structures are given in L<perldsc> and
+L<perllol>.  Examples of structures and object-oriented classes are
+in L<perltoot>.
 
 =head2 How can I use a reference as a hash key?
 
-You can't do this directly, but you could use the standard Tie::Refhash
-module distributed with perl.
+(contributed by brian d foy and Ben Morrow)
 
-=head1 Data: Misc
+Hash keys are strings, so you can't really use a reference as the key.
+When you try to do that, perl turns the reference into its stringified
+form (for instance, C<HASH(0xDEADBEEF)>). From there you can't get
+back the reference from the stringified form, at least without doing
+some extra work on your own.
 
-=head2 How do I handle binary data correctly?
+Remember that the entry in the hash will still be there even if
+the referenced variable  goes out of scope, and that it is entirely
+possible for Perl to subsequently allocate a different variable at
+the same address. This will mean a new variable might accidentally
+be associated with the value for an old.
 
-Perl is binary clean, so this shouldn't be a problem.  For example,
-this works fine (assuming the files are found):
+If you have Perl 5.10 or later, and you just want to store a value
+against the reference for lookup later, you can use the core
+Hash::Util::Fieldhash module. This will also handle renaming the
+keys if you use multiple threads (which causes all variables to be
+reallocated at new addresses, changing their stringification), and
+garbage-collecting the entries when the referenced variable goes out
+of scope.
 
-    if (`cat /vmunix` =~ /gzip/) {
-       print "Your kernel is GNU-zip enabled!\n";
-    }
+If you actually need to be able to get a real reference back from
+each hash entry, you can use the Tie::RefHash module, which does the
+required work for you.
 
-On some systems, however, you have to play tedious games with "text"
-versus "binary" files.  See L<perlfunc/"binmode">.
+=head1 Data: Misc
+
+=head2 How do I handle binary data correctly?
 
-If you're concerned about 8-bit ASCII data, then see L<perllocale>.
+Perl is binary clean, so it can handle binary data just fine.
+On Windows or DOS, however, you have to use C<binmode> for binary
+files to avoid conversions for line endings. In general, you should
+use C<binmode> any time you want to work with binary data.
 
+Also see L<perlfunc/"binmode"> or L<perlopentut>.
+
+If you're concerned about 8-bit textual data then see L<perllocale>.
 If you want to deal with multibyte characters, however, there are
 some gotchas.  See the section on Regular Expressions.
 
@@ -1276,80 +2400,123 @@ some gotchas.  See the section on Regular Expressions.
 Assuming that you don't care about IEEE notations like "NaN" or
 "Infinity", you probably just want to use a regular expression.
 
-   warn "has nondigits"        if     /\D/;
-    warn "not a natural number" unless /^\d+$/;             # rejects -3
-    warn "not an integer"       unless /^-?\d+$/;           # rejects +3
-   warn "not an integer"       unless /^[+-]?\d+$/;
-   warn "not a decimal number" unless /^-?\d+\.?\d*$/;  # rejects .2
-   warn "not a decimal number" unless /^-?(?:\d+(?:\.\d*)?|\.\d+)$/;
-   warn "not a C float"
-       unless /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/;
-
-If you're on a POSIX system, Perl's 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
-isn't a C float.  The C<is_numeric> function is a front end to C<getnum>
-if you just want to say, ``Is this a float?''
-
-    sub getnum {
-        use POSIX qw(strtod);
-        my $str = shift;
-        $str =~ s/^\s+//;
-        $str =~ s/\s+$//;
-        $! = 0;
-        my($num, $unparsed) = strtod($str);
-        if (($str eq '') || ($unparsed != 0) || $!) {
-            return undef;
-        } else {
-            return $num;
-        } 
-    } 
-
-    sub is_numeric { defined &getnum } 
-
-Or you could check out
-http://www.perl.com/CPAN/modules/by-module/String/String-Scanf-1.1.tar.gz
-instead.  The POSIX module (part of the standard Perl distribution)
-provides the C<strtol> and C<strtod> for converting strings to double
+       if (/\D/)            { print "has nondigits\n" }
+       if (/^\d+$/)         { print "is a whole number\n" }
+       if (/^-?\d+$/)       { print "is an integer\n" }
+       if (/^[+-]?\d+$/)    { print "is a +/- integer\n" }
+       if (/^-?\d+\.?\d*$/) { print "is a real number\n" }
+       if (/^-?(?:\d+(?:\.\d*)?|\.\d+)$/) { print "is a decimal number\n" }
+       if (/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/)
+                       { print "a C float\n" }
+
+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 isn't a C float.  The C<is_numeric> function is a front end to
+C<getnum> if you just want to say, "Is this a float?"
+
+       sub getnum {
+               use POSIX qw(strtod);
+               my $str = shift;
+               $str =~ s/^\s+//;
+               $str =~ s/\s+$//;
+               $! = 0;
+               my($num, $unparsed) = strtod($str);
+               if (($str eq '') || ($unparsed != 0) || $!) {
+                               return undef;
+                       }
+               else {
+                       return $num;
+                       }
+               }
+
+       sub is_numeric { defined getnum($_[0]) }
+
+Or you could check out the L<String::Scanf> module on the CPAN
+instead. The C<POSIX> module (part of the standard Perl distribution)
+provides the C<strtod> and C<strtol> for converting strings to double
 and longs, respectively.
 
 =head2 How do I keep persistent data across program calls?
 
 For some specific applications, you can use one of the DBM modules.
-See L<AnyDBM_File>.  More generically, you should consult the
-FreezeThaw, Storable, or Class::Eroot modules from CPAN.
+See L<AnyDBM_File>.  More generically, you should consult the C<FreezeThaw>
+or C<Storable> modules from CPAN.  Starting from Perl 5.8 C<Storable> is part
+of the standard distribution.  Here's one example using C<Storable>'s C<store>
+and C<retrieve> functions:
+
+       use Storable;
+       store(\%hash, "filename");
+
+       # 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 is nice for printing out
-data structures, and FreezeThaw for copying them.  For example:
+The C<Data::Dumper> module on CPAN (or the 5.005 release of Perl) is great
+for printing out data structures.  The C<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);
+       $r2 = dclone($r1);
 
-    use FreezeThaw qw(freeze thaw);
-    $new = thaw freeze $old;
+Where C<$r1> can be a reference to any kind of data structure you'd like.
+It will be deeply copied.  Because C<dclone> takes and returns references,
+you'd have to add extra punctuation if you had a hash of arrays that
+you wanted to copy.
 
-Where $old can be (a reference to) any kind of data structure you'd like.
-It will be deeply copied.
+       %newhash = %{ dclone(\%oldhash) };
 
 =head2 How do I define methods for every class/object?
 
-Use the UNIVERSAL class (see L<UNIVERSAL>).
+(contributed by Ben Morrow)
+
+You can use the C<UNIVERSAL> class (see L<UNIVERSAL>). However, please
+be very careful to consider the consequences of doing this: adding
+methods to every object is very likely to have unintended
+consequences. If possible, it would be better to have all your object
+inherit from some common base class, or to use an object system like
+Moose that supports roles.
 
 =head2 How do I verify a credit card checksum?
 
-Get the Business::CreditCard module from CPAN.
+Get the C<Business::CreditCard> module from CPAN.
+
+=head2 How do I pack arrays of doubles or floats for XS code?
+
+The arrays.h/arrays.c code in the C<PGPLOT> module on CPAN does just this.
+If you're doing a lot of float or double processing, consider using
+the C<PDL> module from CPAN instead--it makes number-crunching easy.
+
+See L<http://search.cpan.org/dist/PGPLOT> for the code.
+
+=head1 REVISION
+
+Revision: $Revision$
+
+Date: $Date$
+
+See L<perlfaq> for source control details and availability.
 
 =head1 AUTHOR AND COPYRIGHT
 
-Copyright (c) 1997, 1998 Tom Christiansen and Nathan Torkington.
-All rights reserved.
+Copyright (c) 1997-2009 Tom Christiansen, Nathan Torkington, and
+other authors as noted. All rights reserved.
 
-When included as part of the Standard Version of Perl, or as part of
-its complete documentation whether printed or otherwise, this work
-may be distributed only under the terms of Perl's Artistic License.
-Any distribution of this file or derivatives thereof I<outside>
-of that package require that special arrangements be made with
-copyright holder.
+This documentation is free; you can redistribute it and/or modify it
+under the same terms as Perl itself.
 
 Irrespective of its distribution, all code examples in this file
 are hereby placed into the public domain.  You are permitted and