The official documentation for the function unlink
says it will be on false
error, but when I try to test its value for false, the compiler hates me:
#!/usr/bin/perl
use utf8;
use strict;
use warnings;
my $fichero = "una_prueba";
if (system("touch", $fichero) != 0) {
die "No se pudo crear $fichero (estatus $?)";
}
print "Fichero $fichero creado.\n";
if (unlink($fichero) == false) {
die "No se pudo remover $fichero: $!";
}
print "Fichero $fichero removido.\n";
exit(0);
When I try to compile that program, the compiler gives me this error and does nothing:
Bareword "false" not allowed while "strict subs" in use at ejemplo-falso line 15.
Execution of ejemplo-falso aborted due to compilation errors.
Thinking that maybe I had to mark the value as a string, I changed it like this:
if (unlink($fichero) == "false") {
When I did that, this time the program was able to run, but with this mysterious complaint:
Fichero una_prueba creado.
Argument "false" isn't numeric in numeric eq (==) at ejemplo-falso line 15.
Fichero una_prueba removido.
Since it worked fine, is there really a problem with writing it like this?
Should that warning be heeded there — or not?
Indeed, the fundamental question here is how should (or should n't ) a boolean value be compared in Perl?
This question was inspired by this SO question and also this question here . I'd rather wait for the community to reply here rather than leave a reply of my own.
Every expression in Perl can be evaluated in a boolean context.
So in your example:
Or if you just want to test the false case, you can negate the expression like this:
There are other ways too; you can choose according to your preference and context:
In this case, Perl will execute what to the right of
or
, only if what to the left evaluates to false. (If you want to run it only in the true case, I changed theor
to aand
). One note: you can use||
instead ofor
and&&
instead ofand
.There is also the ternary operator :
In all cases, Perl decides which expressions are "true" and "false" according to rules that can be simplified like this. The following values are false. The rest are true:
undef
0
(the number zero)""
(the empty string)"0"
(the string that contains only "zero")And with that information, we can reason other common cases:
"0.0"
it's true"0.0"+0
is false, because it is evaluated in numerical context, and so the result is0
that it is false)2-3+1
is false, because it is a mathematical expression that results in0
Perl does not have a data type
booleano
like other languages and therefore does not have keywords for that purpose, such as false or true .However it evaluates Boolean expressions all the time for decision making.
In a
if
, any expression that returns 0, '' orundef
is taken as false and the rest is taken as true (see other cases of false below).To fix your problem, you should modify the block
if
as follows:Personally, I would also change the
if
to expressions that include theand
and operatorsor
. Which in practice are equivalent to if and else respectively.More cases that return false:
Be sure to see the answer @Flimzy, it includes very good notes on other cases where it can result in false.
There is another false value: the value that comes from comparative operators like (0 > 1). It's kind of false that is equal to "" as a string and 0 as a number, but it doesn't cause warnings when used as a number like you would if it were
undef
. That special value is called fake magic from time to time. ( * )According to this post on stack overflow, there are other variants that are also considered false in conditionals: