--- "Randal L. Schwartz" <[EMAIL PROTECTED]> wrote:
> 
> The most comprehensive test for a real number is to let Perl
> do it itself:
> 
>     sub is_number {
>       my $bad = 0;
>       local $SIG{__WARN__} = sub { $bad++ };
>       local $^W = 1;
>       my $guess = shift;
>       $guess += 0;
>       return not $bad;
>     }

This is lovely, and a great opportunity to show some new toys to
beginners, as well as some well-placed caveats. With your indulgence,
I'll try to break this down for the newbies. :)

>     sub is_number {

Declaring the function modularizes the code for reuse, and declares a
block scope (which we'll be using).

>       my $bad = 0;

my() makes $bad private to the function. It doesn't exist outside this
scope.

>       local $SIG{__WARN__} = sub { $bad++ };

%SIG is the magical global Perl table in which you can put signal
handlers, so that you can do things like cleanup tempfiles if you get
an interrupt signal (someone hits CTRL-C while your script is running).
The __WARN__ tag represents the handler called when something triggers
a warning in perl, such as when -w is enabled at the command-line.

local() stores whatever was in the global value, and replaces it with
the new value, but at the end of the current scope will put the old
value back.  (You can't use my() on magical globals like %SIG and
expect them to work normally.) Be careful with this, though -- if you
call some other function from this scope, the value of $SIG{__WARN__}
will still be the routine that increments $bad, but it won't be able to
see the $bad we made with my()!

The handler function for warnings is here set to a simple anonymous
routine which increments $bad. (Note that both $bad and the routine go
away at the end of the scope.)

>       local $^W = 1;

$^W is set be turning on the -w switch. It means warnings are active.
It's a magical Perl global, too, so we localize it here so that we can
set it on, but it won't affect anything outside this block (unless we
pass control out ourselves!), and will be automagically restored at the
end of the block.

>       my $guess = shift;

We create another private variable called $guess, and populate it with
the shift operator, which removes element 0 from @_ (the list of
arguments passed to the function) and returns it. $guess is now the
function's first argument.

>       $guess += 0;

By adding zero, we use $guess in a numeric context without actually
changing it's value. For any valid number format that Perl accepts,
this works and is silent, but if an invalid value is passed in (such as
"foo", or nothing at all), it triggers a warning. The warning handler
istalled above increments $bad to indicate the error.

>       return not $bad;

$bad is now a boolean value indicating whether or not an invalid value
was passed in. Since we want to know if the number was "good", we
return the boolean inversion of the value of $bad.

>     }

Now, calling is_number($val) will give you a boolean indicator of
whether  the value in $val is a perl number. =o)

It doesn't let you say 1,000 however, or 1_000 (which the Perl compiler
recognozes if it's a bareword, but not in quotes). Neither of these are
significant problems. If you wanted to strip such characters with s///
it would be trivial.



=====
print "Just another Perl Hacker\n"; # edited for readability =o)
=============================================================
Real friends are those whom, when you inconvenience them, are bothered less by it than 
you are. -- me. =o) 
=============================================================
"There are trivial truths and there are great Truths.
 The opposite of a trival truth is obviously false.
 The opposite of a great Truth is also true."  -- Neils Bohr

__________________________________________________
Do You Yahoo!?
Get personalized email addresses from Yahoo! Mail - only $35 
a year!  http://personal.mail.yahoo.com/

Reply via email to