perlfaq typos
[p5sagit/p5-mst-13.2.git] / pod / perlfaq4.pod
index 21daac6..aa6b6a5 100644 (file)
@@ -1,6 +1,6 @@
 =head1 NAME
 
-perlfaq4 - Data Manipulation ($Revision: 1.24 $, $Date: 1998/07/05 15:07:20 $)
+perlfaq4 - Data Manipulation ($Revision: 1.26 $, $Date: 1998/08/05 12:04:00 $)
 
 =head1 DESCRIPTION
 
@@ -17,8 +17,8 @@ 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
+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
@@ -61,13 +61,20 @@ umask(), or sysopen(), which all want permissions in octal.
 
 =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 int() merely truncates toward 0.  For rounding to a
+certain number of digits, sprintf() or printf() is usually the easiest
+route.
+
+    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.
 
+    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
 distribution) implements the trigonometric functions. Internally it
@@ -83,7 +90,7 @@ need yourself.
 
 =head2 How do I convert bits into ints?
 
-To turn a string of 1s and 0s like '10110110' into a scalar containing
+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">):
 
@@ -135,15 +142,20 @@ Get the http://www.perl.com/CPAN/modules/by-module/Roman module.
 
 =head2 Why aren't my random numbers random?
 
-John von Neumann said, ``Anyone who attempts to generate random numbers by
-deterministic means is, of course, living in a state of sin.''  
-
 The short explanation is that you're getting pseudorandom numbers, not
-random ones, because that's how these things work.  A longer explanation
-is available on http://www.perl.com/CPAN/doc/FMTEYEWTK/random, courtesy
-of Tom Phoenix.
-
-You should also check out the Math::TrulyRandom module from CPAN.
+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
+pseudorandom generator than comes with your operating system, look at
+``Numerical Recipes in C'' at http://nr.harvard.edu/nr/bookc.html .
 
 =head1 Data: Dates
 
@@ -163,36 +175,49 @@ You can find the week of the year by dividing this by 7:
 
     $week_of_year = int($day_of_year / 7);
 
-Of course, this believes that weeks start at zero.
+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 can I compare two date strings?
+=head2 How can I compare two dates and find the difference?
 
-Use the Date::Manip or Date::DateCalc modules from CPAN.
+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.
 
 =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 timelocal in the standard
-Time::Local module.  Otherwise, you should look into one of the
-Date modules from CPAN.
+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.
 
 =head2 How can I find the Julian Day?
 
-Neither Date::Manip nor Date::DateCalc deal with Julian days.
-Instead, there is an example of Julian date calculation in
-http://www.perl.com/CPAN/authors/David_Muir_Sharnoff/modules/Time/JulianDay.pm.gz,
-which should help.
+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
+.
 
 =head2 Does Perl have a year 2000 problem?  Is Perl Y2K compliant?
 
-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.
+Short answer: No, Perl does not have a Year 2000 problem.  Yes,
+Perl is Y2K compliant.  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.
 
 When gmtime() and localtime() are used in scalar context they return
 a timestamp string that contains a fully-expanded year.  For example,
@@ -215,17 +240,17 @@ addresses, etc.) for details.
 
 =head2 How do I unescape a string?
 
-It depends just what you mean by "escape".  URL escapes are dealt with
-in L<perlfaq9>.  Shell escapes with the backslash (\)
+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:
 
     s/\\(.)/$1/g;
 
-Note that this won't expand \n or \t or any other special escapes.
+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 "abbcccd" into "abccd":
+To turn C<"abbcccd"> into C<"abccd">:
 
     s/(.)\1/$1/g;
 
@@ -242,20 +267,30 @@ arbitrary expressions:
 
     print "That yields ${\($n + 5)} widgets\n";
 
-See also "How can I expand variables in text strings?" in this section
-of the FAQ.
+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.
+
+See also ``How can I expand variables in text strings?'' in this
+section of the FAQ.
 
 =head2 How do I find matching/nesting anything?
 
-This isn't something that can be tackled 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 parser.
+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
+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/ .
 
-One destructive, inside-out approach that you might try is to pull
-out the smallest nesting parts one at a time:
+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
@@ -287,13 +322,13 @@ Use Text::Wrap (part of the standard perl distribution):
     use Text::Wrap;
     print wrap("\t", '  ', @paragraphs);
 
-The paragraphs you give to Text::Wrap may not contain embedded
+The paragraphs you give to Text::Wrap should not contain embedded
 newlines.  Text::Wrap doesn't justify the lines (flush-right).
 
 =head2 How can I access/change the first N letters of a string?
 
 There are many ways.  If you just want to grab a copy, use
-substr:
+substr():
 
     $first_byte = substr($a, 0, 1);
 
@@ -302,15 +337,16 @@ use substr() as an lvalue:
 
     substr($a, 0, 3) = "Tom";
 
-Although those with a regexp kind of thought process will likely prefer
+Although those with a pattern matching kind of thought process will
+likely prefer:
 
     $a =~ s/^.../Tom/;
 
 =head2 How do I change the Nth occurrence of something?
 
-You have to keep track.  For example, let's say you want
-to change the fifth occurrence of "whoever" or "whomever"
-into "whosoever" or "whomsoever", case insensitively.
+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.
 
     $count = 0;
     s{((whom?)ever)}{
@@ -331,7 +367,7 @@ loop, keeping count of matches.
         }
     }
 
-That prints out: "The third fish is a red one."  You can also use a
+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;
@@ -342,7 +378,7 @@ 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":
+    $string = "ThisXlineXhasXsomeXx'sXinXit";
     $count = ($string =~ tr/X//);
     print "There are $count X charcters in the string";
 
@@ -364,7 +400,7 @@ To make the first letter of each word upper case:
 
 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 E<lt>comdog@computerdog.comE<gt>):
+Foy):
 
     $string =~ s/ (
                  (^\w)    #at the beginning of the line
@@ -384,7 +420,7 @@ To force each word to be lower case, with the first letter upper case:
 
 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.
+See L<perllocale> for endless details on locales.
 
 =head2 How can I split a [character] delimited string except when inside
 [character]? (Comma-separated files)
@@ -440,7 +476,7 @@ Or more nicely written as:
        s/\s+$//;
     }
 
-This idiom takes advantage of the for(each) loop's aliasing
+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:
@@ -504,7 +540,7 @@ variables as entries in some special hash.  For example:
     );
     $text =~ s/\$(\w+)/$user_defs{$1}/g;
 
-See also "How do I expand function calls in a string?" in this section
+See also ``How do I expand function calls in a string?'' in this section
 of the FAQ.
 
 =head2 What's wrong with always quoting "$vars"?