summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlperl/lib/pods/perlfaq4.pod
diff options
context:
space:
mode:
Diffstat (limited to 'Master/tlpkg/tlperl/lib/pods/perlfaq4.pod')
-rw-r--r--Master/tlpkg/tlperl/lib/pods/perlfaq4.pod373
1 files changed, 237 insertions, 136 deletions
diff --git a/Master/tlpkg/tlperl/lib/pods/perlfaq4.pod b/Master/tlpkg/tlperl/lib/pods/perlfaq4.pod
index 45cc9e044dd..eb18743f822 100644
--- a/Master/tlpkg/tlperl/lib/pods/perlfaq4.pod
+++ b/Master/tlpkg/tlperl/lib/pods/perlfaq4.pod
@@ -13,7 +13,7 @@ numbers, dates, strings, arrays, hashes, and miscellaneous data issues.
For the long explanation, see David Goldberg's "What Every Computer
Scientist Should Know About Floating-Point Arithmetic"
-(http://docs.sun.com/source/806-3568/ncg_goldberg.html).
+(L<http://web.cse.msu.edu/~cse320/Documents/FloatingPoint.pdf>).
Internally, your computer represents floating-point numbers in binary.
Digital (as in powers of two) computers cannot store all numbers
@@ -25,8 +25,8 @@ 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
-C<printf> or C<sprintf> function. See the L<"Floating Point
-Arithmetic"|perlop> for more details.
+C<printf> or C<sprintf> function. See
+L<perlop/"Floating Point Arithmetic"> for more details.
printf "%.2f", 10/3;
@@ -117,8 +117,8 @@ the real axis into the complex plane, for example the inverse sine of
Rounding in financial applications can have serious implications, and
the rounding method used should be specified precisely. In these
-cases, it probably pays not to trust whichever system rounding is
-being used by Perl, but to instead implement the rounding function you
+cases, it probably pays not to trust whichever system of rounding is
+being used by Perl, but instead to implement the rounding function you
need yourself.
To see why, notice how you'll still have an issue on half-way-point
@@ -131,7 +131,7 @@ alternation:
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.
+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?
@@ -143,7 +143,7 @@ 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,
+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.
@@ -244,7 +244,7 @@ Using C<pack> and C<unpack> for larger strings:
substr("0" x 32 . "11110101011011011111011101111", -32)));
$dec = sprintf("%d", $int);
- # substr() is used to left pad a 32 character string with zeros.
+ # substr() is used to left-pad a 32-character string with zeros.
Using C<Bit::Vector>:
@@ -285,7 +285,9 @@ 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
+they have a number but really it's a string or vice versa. To avoid this,
+stringify the arguments explicitly (using C<""> or C<qq()>) or convert them
+to numbers explicitly (using C<0+$arg>). The rest arise because
the programmer says:
if ("\020\020" & "\101\101") {
@@ -326,12 +328,12 @@ To call a function on each integer in a (small) range, you B<can> use:
@results = map { some_func($_) } (5 .. 25);
-but you should be aware that the C<..> operator creates an array of
+but you should be aware that the C<..> operator creates a list 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++) {
+ for ($i=5; $i <= 500_005; $i++) {
push(@results, some_func($i));
}
@@ -360,7 +362,7 @@ 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
+(despite appearances caused by bugs in your programs :-). The
F<random> article in the "Far More Than You Ever Wanted To Know"
collection in L<http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz>, courtesy
of Tom Phoenix, talks more about this. John von Neumann said, "Anyone
@@ -405,10 +407,11 @@ integers (inclusive), For example: C<random_int_between(50,120)>.
=head2 How do I find the day or week of the year?
-The C<localtime> function returns the day of the year. Without an
+The day of the year is in the list returned
+by the C<localtime> function. Without an
argument C<localtime> uses the current time.
- $day_of_year = (localtime)[7];
+ my $day_of_year = (localtime)[7];
The C<POSIX> module can also format a date as the day of the year or
week of the year.
@@ -424,7 +427,14 @@ a time in epoch seconds for the argument to C<localtime>.
my $week_of_year = strftime "%W",
localtime( mktime( 0, 0, 0, 18, 11, 87 ) );
-The C<Date::Calc> module provides two functions to calculate these.
+You can also use C<Time::Piece>, which comes with Perl and provides a
+C<localtime> that returns an object:
+
+ use Time::Piece;
+ my $day_of_year = localtime->yday;
+ my $week_of_year = localtime->week;
+
+The C<Date::Calc> module provides two functions to calculate these, too:
use Date::Calc;
my $day_of_year = Day_of_Year( 1987, 12, 18 );
@@ -446,7 +456,7 @@ 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
+thus cannot be used to determine reliably the current century or
millennium.
=head2 How can I compare two dates and find the difference?
@@ -454,43 +464,74 @@ millennium.
(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.
+Life isn't always that simple though.
+
+The C<Time::Piece> module, which comes with Perl, replaces C<localtime>
+with a version that returns an object. It also overloads the comparison
+operators so you can compare them directly:
+
+ use Time::Piece;
+ my $date1 = localtime( $some_time );
+ my $date2 = localtime( $some_other_time );
+
+ if( $date1 < $date2 ) {
+ print "The date was in the past\n";
+ }
+
+You can also get differences with a subtraction, which returns a
+C<Time::Seconds> object:
+
+ my $diff = $date1 - $date2;
+ print "The difference is ", $date_diff->days, " days\n";
+
+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
-C<Time::Local> module. Otherwise, you should look into the C<Date::Calc>
-and C<Date::Manip> modules from CPAN.
+C<Time::Local> module. Otherwise, you should look into the C<Date::Calc>,
+C<Date::Parse>, and C<Date::Manip> modules from CPAN.
=head2 How can I find the Julian Day?
(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 use the C<Time::Piece> module, part of the Standard Library,
+which can convert a date/time to a Julian Day:
-You can also try the C<DateTime> module, which can convert a date/time
-to a Julian Day.
+ $ perl -MTime::Piece -le 'print localtime->julian_day'
+ 2455607.7959375
- $ perl -MDateTime -le'print DateTime->today->jd'
- 2453401.5
+Or the modified Julian Day:
-Or the modified Julian Day
-
- $ perl -MDateTime -le'print DateTime->today->mjd'
- 53401
+ $ perl -MTime::Piece -le 'print localtime->mjd'
+ 55607.2961226851
Or even the day of the year (which is what some people think of as a
-Julian day)
+Julian day):
+
+ $ perl -MTime::Piece -le 'print localtime->yday'
+ 45
+
+You can also do the same things with the C<DateTime> module:
+ $ perl -MDateTime -le'print DateTime->today->jd'
+ 2453401.5
+ $ perl -MDateTime -le'print DateTime->today->mjd'
+ 53401
$ perl -MDateTime -le'print DateTime->today->doy'
31
+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):
+
+ $ perl -MTime::JulianDay -le 'print local_julian_day( time )'
+ 55608
+
=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>
@@ -498,8 +539,10 @@ 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.
+To do it correctly, you can use one of the C<Date> modules since they
+work with calendars instead of times. The C<DateTime> module makes it
+simple, and give you the same time of day, only the day before,
+despite daylight saving time changes:
use DateTime;
@@ -519,24 +562,35 @@ function.
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.
+and from summer time throws this off. For example, the rest of the
+suggestions will be wrong sometimes:
+
+Starting with Perl 5.10, C<Time::Piece> and C<Time::Seconds> are part
+of the standard distribution, so you might think that you could do
+something like this:
+
+ use Time::Piece;
+ use Time::Seconds;
+
+ my $yesterday = localtime() - ONE_DAY; # WRONG
+ print "Yesterday was $yesterday\n";
-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:
+The C<Time::Piece> module exports a new C<localtime> that returns an
+object, and C<Time::Seconds> exports the C<ONE_DAY> constant that is a
+set number of seconds. This means that it always gives the time 24
+hours ago, which is not always yesterday. This can cause problems
+around the end of daylight saving time when there's one day that is 25
+hours long.
+
+You have the same problem with C<Time::Local>, which will give the wrong
+answer for those same special cases:
# 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];
+ my ($d, $m, $y) = ( localtime $today-86400 )[3..5]; # WRONG
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 or 2038 problem? Is Perl Y2K compliant?
(contributed by brian d foy)
@@ -545,21 +599,21 @@ Perl itself never had a Y2K problem, although that never stopped people
from creating Y2K problems on their own. See the documentation for
C<localtime> for its proper use.
-Starting with Perl 5.11, C<localtime> and C<gmtime> can handle dates past
+Starting with Perl 5.12, C<localtime> and C<gmtime> can handle dates past
03:14:08 January 19, 2038, when a 32-bit based time would overflow. You
still might get a warning on a 32-bit C<perl>:
- % perl5.11.2 -E 'say scalar localtime( 0x9FFF_FFFFFFFF )'
+ % perl5.12 -E 'say scalar localtime( 0x9FFF_FFFFFFFF )'
Integer overflow in hexadecimal number at -e line 1.
Wed Nov 1 19:42:39 5576711
On a 64-bit C<perl>, you can get even larger dates for those really long
running projects:
- % perl5.11.2 -E 'say scalar gmtime( 0x9FFF_FFFFFFFF )'
+ % perl5.12 -E 'say scalar gmtime( 0x9FFF_FFFFFFFF )'
Thu Nov 2 00:42:39 5576711
-You're still out of luck if you need to keep tracking of decaying protons
+You're still out of luck if you need to keep track of decaying protons
though.
=head1 Data: Strings
@@ -594,11 +648,11 @@ This won't expand C<"\n"> or C<"\t"> or any other special escapes.
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
+store the matched character in the back-reference C<\g1> 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;
+ s/(.)\g1/$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
@@ -849,7 +903,7 @@ that C<s> after the apostrophe? You could try a regular expression:
Now, what if you don't want to capitalize that "and"? Just use
L<Text::Autoformat> and get on with the next problem. :)
-=head2 How can I split a [character] delimited string except when inside [character]?
+=head2 How can I split a [character]-delimited string except when inside [character]?
Several modules can handle this sort of parsing--C<Text::Balanced>,
C<Text::CSV>, C<Text::CSV_XS>, and C<Text::ParseWords>, among others.
@@ -890,14 +944,14 @@ Perl distribution) lets you say:
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.
+can do that with a pair of substitutions:
s/^\s+//;
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.
+might not matter to you, though:
s/^\s+|\s+$//g;
@@ -906,30 +960,29 @@ 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
+absolute 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.
+would remove all by itself:
- while( <> )
- {
+ while( <> ) {
s/^\s+|\s+$//g;
print "$_\n";
}
-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
+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.
+embedded newline, so it doesn't remove it. This pattern 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,
+and replace it with nothing. If you 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.
+(since that includes a newline), just match the other whitespace:
$string =~ s/^[\t\f ]+|[\t\f ]+$//mg;
@@ -1119,16 +1172,18 @@ Stringification also destroys arrays.
=head2 Why don't my E<lt>E<lt>HERE documents work?
-Check for these three things:
+Here documents are found in L<perlop>. Check for these three things:
=over 4
=item There must be no space after the E<lt>E<lt> part.
-=item There (probably) should be a semicolon at the end.
+=item There (probably) should be a semicolon at the end of the opening token
=item You can't (easily) have any space in front of the tag.
+=item There needs to be at least a line separator after the end token.
+
=back
If you want to indent the text in the here document, you
@@ -1162,7 +1217,7 @@ subsequent line.
sub fix {
local $_ = shift;
my ($white, $leader); # common whitespace and common leading string
- if (/^\s*(?:([^\w\s]+)(\s*).*\n)(?:\s*\1\2?.*\n)+$/) {
+ if (/^\s*(?:([^\w\s]+)(\s*).*\n)(?:\s*\g1\g2?.*\n)+$/) {
($white, $leader) = ($2, quotemeta($1));
} else {
($white, $leader) = (/^(\s+)/, '');
@@ -1222,7 +1277,7 @@ for list operations, so list operations also work on arrays:
wash_animals( qw( dog cat bird ) );
wash_animals( @animals );
-Array operations, which change the scalars, reaaranges them, or adds
+Array operations, which change the scalars, rearranges them, or adds
or subtracts some scalars, only work on arrays. These can't work on a
list, which is fixed. Array operations include C<shift>, C<unshift>,
C<push>, C<pop>, and C<splice>.
@@ -1269,7 +1324,7 @@ context. The comma operator (yes, it's an operator!) in scalar
context evaluates its lefthand side, throws away the result, and
evaluates it's righthand side and returns the result. In effect,
that list-lookalike assigns to C<$scalar> it's rightmost value. Many
-people mess this up becuase they choose a list-lookalike whose
+people mess this up because they choose a list-lookalike whose
last element is also the count they expect:
my $scalar = ( 1, 2, 3 ); # $scalar gets 3, accidentally
@@ -1562,53 +1617,23 @@ that satisfies the condition.
=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 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. For example, imagine a list node like this:
-
- $node = {
- VALUE => 42,
- LINK => undef,
- };
-
-You could walk the list this way:
+(contributed by brian d foy)
- print "List: ";
- for ($node = $head; $node; $node = $node->{LINK}) {
- print $node->{VALUE}, " ";
- }
- print "\n";
+Perl's arrays do not have a fixed size, so you don't need linked lists
+if you just want to add or remove items. You can use array operations
+such as C<push>, C<pop>, C<shift>, C<unshift>, or C<splice> to do
+that.
-You could add to the list this way:
+Sometimes, however, linked lists can be useful in situations where you
+want to "shard" an array so you have have many small arrays instead of
+a single big array. You can keep arrays longer than Perl's largest
+array index, lock smaller arrays separately in threaded programs,
+reallocate less memory, or quickly insert elements in the middle of
+the chain.
- 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.
+Steve Lembark goes through the details in his YAPC::NA 2009 talk "Perly
+Linked Lists" ( http://www.slideshare.net/lembark/perly-linked-lists ),
+although you can just use his C<LinkedList::Single> module.
=head2 How do I handle circular lists?
X<circular> X<array> X<Tie::Cycle> X<Array::Iterator::Circular>
@@ -1745,7 +1770,7 @@ 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<List::Permutor> 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
@@ -2212,7 +2237,7 @@ 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
+like the slowdown 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?
@@ -2347,7 +2372,8 @@ Or if you really want to save space:
Either stringify the structure yourself (no fun), or else
get the MLDBM (which uses Data::Dumper) module from CPAN and layer
-it on top of either DB_File or GDBM_File.
+it on top of either DB_File or GDBM_File. You might also try DBM::Deep, but
+it can be a bit slow.
=head2 How can I make my hash remember the order I put elements into it?
@@ -2418,7 +2444,7 @@ Usually a hash ref, perhaps like this:
PALS => [ "Norbert", "Rhys", "Phineas"],
};
-References are documented in L<perlref> and the upcoming L<perlreftut>.
+References are documented in L<perlref> and 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>.
@@ -2451,11 +2477,79 @@ 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.
+=head2 How can I check if a key exists in a multilevel hash?
+
+(contributed by brian d foy)
+
+The trick to this problem is avoiding accidental autovivification. If
+you want to check three keys deep, you might naïvely try this:
+
+ my %hash;
+ if( exists $hash{key1}{key2}{key3} ) {
+ ...;
+ }
+
+Even though you started with a completely empty hash, after that call to
+C<exists> you've created the structure you needed to check for C<key3>:
+
+ %hash = (
+ 'key1' => {
+ 'key2' => {}
+ }
+ );
+
+That's autovivification. You can get around this in a few ways. The
+easiest way is to just turn it off. The lexical C<autovivification>
+pragma is available on CPAN. Now you don't add to the hash:
+
+ {
+ no autovivification;
+ my %hash;
+ if( exists $hash{key1}{key2}{key3} ) {
+ ...;
+ }
+ }
+
+The C<Data::Diver> module on CPAN can do it for you too. Its C<Dive>
+subroutine can tell you not only if the keys exist but also get the
+value:
+
+ use Data::Diver qw(Dive);
+
+ my @exists = Dive( \%hash, qw(key1 key2 key3) );
+ if( ! @exists ) {
+ ...; # keys do not exist
+ }
+ elsif( ! defined $exists[0] ) {
+ ...; # keys exist but value is undef
+ }
+
+You can easily do this yourself too by checking each level of the hash
+before you move onto the next level. This is essentially what
+C<Data::Diver> does for you:
+
+ if( check_hash( \%hash, qw(key1 key2 key3) ) ) {
+ ...;
+ }
+
+ sub check_hash {
+ my( $hash, @keys ) = @_;
+
+ return unless @keys;
+
+ foreach my $key ( @keys ) {
+ return unless eval { exists $hash->{$key} };
+ $hash = $hash->{$key};
+ }
+
+ return 1;
+ }
+
=head1 Data: Misc
=head2 How do I handle binary data correctly?
-Perl is binary clean, so it can handle binary data just fine.
+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.
@@ -2469,31 +2563,40 @@ some gotchas. See the section on Regular Expressions.
=head2 How do I determine whether a scalar is a number/whole/integer/float?
Assuming that you don't care about IEEE notations like "NaN" or
-"Infinity", you probably just want to use a regular expression.
+"Infinity", you probably just want to use a regular expression:
- 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" }
+ use 5.010;
+
+ given( $number ) {
+ when( /\D/ )
+ { say "\thas nondigits"; continue }
+ when( /^\d+\z/ )
+ { say "\tis a whole number"; continue }
+ when( /^-?\d+\z/ )
+ { say "\tis an integer"; continue }
+ when( /^[+-]?\d+\z/ )
+ { say "\tis a +/- integer"; continue }
+ when( /^-?(?:\d+\.?|\.\d)\d*\z/ )
+ { say "\tis a real number"; continue }
+ when( /^[+-]?(?=\.?\d)\d*\.?\d*(?:e[+-]?\d+)?\z/i)
+ { say "\tis a C float" }
+ }
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
+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
+function for converting strings to doubles (and also C<POSIX::strtol>
+for longs). 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
+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 {
@@ -2514,9 +2617,7 @@ C<getnum> if you just want to say, "Is this a float?"
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.
+instead.
=head2 How do I keep persistent data across program calls?