This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Generate the warnings masks programatically.
[perl5.git] / pod / perlfaq4.pod
index b4945d3..3200e7a 100644 (file)
@@ -1,6 +1,6 @@
 =head1 NAME
 
-perlfaq4 - Data Manipulation ($Revision: 7996 $)
+perlfaq4 - Data Manipulation ($Revision: 10394 $)
 
 =head1 DESCRIPTION
 
@@ -17,7 +17,7 @@ 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> show the gory details of number representations and
+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
@@ -362,17 +362,16 @@ pseudorandom generator than comes with your operating system, look at
 
 =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()> builtin to get a random number between 0 and
+To get a random number between two values, you can use the C<rand()>
+builtin 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>.
+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.
+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 );
 
@@ -491,14 +490,14 @@ give you the same time of day, only the day before.
 
        print "Yesterday was $yesterday\n";
 
-You can also use the C<Date::Calc> module using its Today_and_Now
+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\n";
+       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
@@ -1007,12 +1006,15 @@ C<Text::Metaphone>, and C<Text::DoubleMetaphone> modules.
 (contributed by brian d foy)
 
 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.
+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>:
+
+       my $string = sprintf 'Say hello to %s and %s', $foo, $bar;
 
 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.
+to their variable's values:
 
        my $foo = 'Fred';
        my $bar = 'Barney';
@@ -1022,17 +1024,22 @@ 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.
+what's left in the string:
 
        $string =~ s/(\$\w+)/$1/eeg; # 'Say hello to Fred and Barney'
 
 The C</e> will also silently ignore violations of strict, replacing
-undefined variable names with the empty string.
-
-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:
+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.
+
+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';
        
@@ -1309,7 +1316,7 @@ 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 equivalant
+finds the element. It's written in C for speed, and its Perl equivalent
 looks like this subroutine:
 
        sub first (&@) {
@@ -1434,7 +1441,7 @@ that satisfies the condition.
 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)
+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.
@@ -1589,14 +1596,18 @@ Or, simply:
        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>
 
-Use the C<List::Permutor> module on CPAN.  If the list is actually an
+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.
+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";
                }
@@ -1604,19 +1615,20 @@ written in XS code and is very efficient.
 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:
+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-Kause ordered permutation generator
+       # Fischer-Krause ordered permutation generator
 
        sub permute (&@) {
                my $code = shift;
@@ -1631,7 +1643,22 @@ and will work on any list:
                }
        }
 
-       permute {print"@_\n"} split;
+       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)?
 
@@ -1799,15 +1826,57 @@ in the 5.004 release or later of Perl for more detail.
 
 =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)
 
-       while ( ($key, $value) = each %hash) {
-               print "$key = $value\n";
+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}
+               ...
                }
 
-If you want it sorted, you'll have to use foreach() on the result of
-sorting the keys as shown in an earlier question.
+Once you have the list of keys, you can process that list before you
+process the hashh 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 on 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 What happens if I add or remove keys from a hash while iterating over it?
 
@@ -1939,7 +2008,7 @@ And these conditions hold
        $hash{'d'}                       is false
        defined $hash{'d'}               is true
        defined $hash{'a'}               is true
-       exists $hash{'a'}                is true (Perl5 only)
+       exists $hash{'a'}                is true (Perl 5 only)
        grep ($_ eq 'a', keys %hash)     is true
 
 If you now say
@@ -1963,7 +2032,7 @@ and these conditions now hold; changes in caps:
        $hash{'d'}                       is false
        defined $hash{'d'}               is true
        defined $hash{'a'}               is FALSE
-       exists $hash{'a'}                is true (Perl5 only)
+       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!
@@ -1987,7 +2056,7 @@ and these conditions now hold; changes in caps:
        $hash{'d'}                       is false
        defined $hash{'d'}               is true
        defined $hash{'a'}               is false
-       exists $hash{'a'}                is FALSE (Perl5 only)
+       exists $hash{'a'}                is FALSE (Perl 5 only)
        grep ($_ eq 'a', keys %hash)     is FALSE
 
 See, the whole entry is gone!
@@ -2002,10 +2071,16 @@ 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?
 
@@ -2219,15 +2294,15 @@ the C<PDL> module from CPAN instead--it makes number-crunching easy.
 
 =head1 REVISION
 
-Revision: $Revision: 7996 $
+Revision: $Revision: 10394 $
 
-Date: $Date: 2006-11-01 09:24:38 +0100 (mer, 01 nov 2006) $
+Date: $Date: 2007-12-09 18:47:15 +0100 (Sun, 09 Dec 2007) $
 
 See L<perlfaq> for source control details and availability.
 
 =head1 AUTHOR AND COPYRIGHT
 
-Copyright (c) 1997-2006 Tom Christiansen, Nathan Torkington, and
+Copyright (c) 1997-2007 Tom Christiansen, Nathan Torkington, and
 other authors as noted. All rights reserved.
 
 This documentation is free; you can redistribute it and/or modify it