Why does perl treat the string "0" as false? [duplicate] - perl

This question already has answers here:
Why is '0' false in Perl?
(6 answers)
Closed 6 years ago.
I found in the text that string '0' is equivalent to 0, hence the condition is false in PERL.
But when I looked at the ASCII table '0' is ASCII 48. So why does perl consider string '0' as a value 0 in this control structure ?
if ('0'){
print "Statement1 \n";
}
else {
print "statement2\n";
}

Because it is specified to do so.
The number 0, the strings '0' and '', the empty list "()", and "undef"
are all false in a boolean context. All other values are true.
Negation of a true value by "!" or "not" returns a special false
value. When evaluated as a string it is treated as '', but as a number, it is treated as 0.
That's the specification. The behavior conforms.
As for why the specification is so written -- Perl makes a practice of implicitly converting between strings and numbers, and in this respect does not use ASCII value but decimal value. Treating '0' in the same manner as 0 in this context is thus consistent with the behavior of allowing '9'+1 to return 10, rather than ':' (the next ASCII value).

Related

How to check if a String is numeric in PowerShell? [duplicate]

This question already has answers here:
Check if string contains numeric value in PowerShell?
(7 answers)
Closed 1 year ago.
How can you check if the whole string is a number?
You can check if a string contains a number with regular expression. Can you use regular expressions as well to find out if a string is only a number, without any other characters?
"abc" is supposed to be false, it's not a number
"abc12" is supposed to be false, it's not a number
"123" is supposed to be true
if you are not using variables, and literal which is one quote, exactly what is in between the quotes.
'abc' -is [String]
'abc12' -is [String]
'123' -is [String]

Perl comparison operator output

I am not exactly sure what the output of a comparison is. For instance, consider
$rr = 1>2;
$qq = 2>1;
print $rr; #nothing printed
print $qq; #1 printed
Is $rr the empty string? Is this behavior documented somewhere? Or how can one tell for sure?
I was looking for the answer in Learning Perl by Schwartz et al., but could not immediately resolve the answer.
http://perldoc.perl.org/perlop.html#Relational-Operators:
Perl operators that return true or false generally return values that can be safely used as numbers. For example, the relational operators in this section and the equality operators in the next one return 1 for true and a special version of the defined empty string, "" , which counts as a zero but is exempt from warnings about improper numeric conversions, just as "0 but true" is.
So it what is returned is something that is an empty string in string context, and 0 in numeric context.

perl how to force boolean to 0/1

I'm trying to get a 0 or 1 in a value for true/false. Here's the code:
use strict;
my %h = (Y => "y");
my $bool_x = 1 & exists $h{X};
my $bool_y = 1 & exists $h{Y};
print("x $bool_x y $bool_y\n");
I needed to add the "1 &" to force it to not be the empty string. Is there a better way to do this? I realize that it's an artifact of the way perl prints the false value, but I need it to be a 0 not the empty string.
The most efficient way to do this is just:
$bool || 0
Your code is far from clear. The & operator is a bitwise operator that behaves differently on numbers and strings, but exists returns a value that will obligingly be the number zero or the empty string depending on what is required of it. perldoc perlop has this to say
Although no warning is currently raised, the result is not well defined when this operation is performed on operands that aren't either numbers (see Integer Arithmetic) nor bitstrings (see Bitwise String Operators)
So because the result of exists is one such value your code is on shakey ground
There is no need to write something arcane, and if you want to represent Perl's internal true and false values by a different pair of values then the conditional operator is the correct choice
my $bool_x = exists $h{X} ? 1 : 0
I believe that's the most readable without being verbose, and that's all that matters here. It's also applicable to any other pair of values that you may choose, such as
my $bool_x = exists $h{X} ? 'Y' : 'N'
There are many ways to "numify" a true/false value.
If $var can contain 1 or any false value, all of these will evaluate to either "0" or "1":
0 + $var
0 | $var
$var || 0
1 * $var
1 & $var (you discovered this one, already)
chr(48+$var)
sprintf "%d", $var
These constructions return a 0/1 value when $var can contain any true or false value:
0 + !!$var ( !! true => 1, !! false => "" )
1 - !$var
$var ? 1 : 0

0, 0e0, 0.0, -0, +0, 000 all mean the same thing to Perl, why?

Just puzzling to me.
Related, but different question:
What does “0 but true” mean in Perl?
Perl doesn't distinguish kinds of numbers. Looking at all of those with a non-CS/programmer eye, they all mean the same thing to me as well: zero. (This is one of the foundations of Perl: it tries to work like people, not like computers. "If it looks like a duck....")
So, if you use them as numbers, they're all the same thing. If you use them as strings, they differ. This does lead to situations where you may need to force one interpretation ("0 but true"; see also "nancy typing"). but by and large it "does the right thing" automatically.
I don't understand, what else should they mean?
You give integer, scientific, floating point, signed integers and octal notations of zero. Why should they differ?
0==0 as everyone, including Larry Wall, knows.
Perl interprets every scalar value as both a string and (potentially) a number. All of those string representations of zero can convert to the integer value 0 , according to perl's conversion rules:
"0", "0.0", "-0", "+0", "000" => Simplest case of straight string to numeric conversion.
"0e0" => In a numeric context, only the leading valid numeric characters are converted, so only the leading "0" is used. For example, "1984abcdef2112" would be interpreted numerically as 1984.
"0 but true" in perl means that a string like "0e0" will evalutate numerically to 0, but in a boolean context will be "true" because the conversion to boolean follows different rules than the strict numeric conversion.
Perl works in contexts. In string context, they are all different. In numeric context, they are all zero.
print "same string\n" if '0' eq '0.0';
print "same number\n" if 0 == 0.0;
'0 but true' in boolean context is true:
print "boolean context\n" if '0 but true';
print "string context\n" if '0 but true' eq '0';
print "numeric context\n" if '0 but true' == 0;

Pass zero in to Getopt::Std

I am using Getopt::Std in a Perl script, and would like to pass in a zero as value. I am checking that values are set correctly using unless(). At the moment unless() is rejecting the value as being unset.
Is there a way to get unless() to accept zero as a valid value (any non-negative integer is valid).
This is probably perfeclty simple, but I've never touched Perl before a few days ago!
Rich
You need to use unless defined <SOMETHING> instead of unless <SOMETHING> , because zero is false in Perl.
Perl 5 has several false values: 0, "0", "", undef, ().
It is important to note that some things may look like they should be false, but aren't. For instance 0.0 is false because it is number that is equivalent to 0, but "0.0" is not (the only strings which are false are the empty string ("") and "0").
It also has the concept of definedness. A variable that has a value (other than undef) assigned to it is said to be defined and will return true when tested with the defined function.
Given that you want an argument to be a non-negative integer, it is probably better to test for that:
unless (defined $value and $value =~ /^[0-9]+$/) {
#blah
}