Perl is a scripting programming language that was quite popular in the early ’90s and lately has fallen in usage, although at the moment of writing it is still in the top 20 in the TIOBE index. It is still widely used in bioinformatics, sysops and projects like git or the Linux kernel among many others. Perl is well known for its concise although often cryptic syntax and powerful one-liners and regular expressions. This is also its curse as it has been accused of being hard to maintain and “write-only”.
The scalar represents a single value, that can be a string, a number, a float, or a reference to a list. We will not get deep into this, but the important idea is that Perl will transform between these different values depending on its needs as other scripting languages do. However, this sometimes is not explicit and it will complain if you use the wrong operator with the wrong type.
0> my $aString = "string" $res = "string" 1> $aString == "string" ? "true" : "false"; Argument "string" isn't numeric in numeric eq (==) at reply input line 1. Argument "string" isn't numeric in numeric eq (==) at reply input line 1. $res = "true" 3> $aString eq "string" ? "true" : "false"; $res = "true"
In the example above, we can see that Perl complained because we used a numeric operator instead of a string operator. Typically, we would execute the script in strict mode without warnings, which will give an error and stop execution.
Perl does not have a boolean type, but different values will be evaluated as “true” or “false”. Quoting the official documentation:
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.
"0 but true" :
- It is a string …
- that can be used as 0 …
- but evaluates as true.
So, we can operate with it like any other string:
0> my $zeroButTrue = "0 but true"; $res = "0 but true" 1> split " ", $zeroButTrue; $res = (0, "but", "true")
but we can also do some maths!! This will not work with other strings if we have strict mode and warnings enabled.
2> 10 + $zeroButTrue; $res = 10 3> my $oneString = "1 string"; $res = "1 string" 4> 10 + $oneString; Argument "1 string" isn't numeric in addition (+) at reply input line 1. $res = 11
However, we can see as well that this is not how 0 behaves:
5> $zeroButTrue ? "true" : "false"; $res = "true" 6> 0 ? "true" : "false"; $res = "false"
The reason behind this odd behaviour is the way *nix systems handle process returns. In these systems, when a process returns 0, it means success or true, the opposite as in Perl or almost any other programming language. Any other number different from 0 is an error, being the value of the output of the error code. Taking these values without processing will create output. Therefore, instead of returning 0, it will return 0 but true and if it is an error, it will return the error code as a value. Error codes are still evaluated as a number, hence they will evaluate as true.
This magic string is indeed a curiosity, and this could have been fixed by simply inverting the result of the return when evaluating (or using unless instead of if), also making the errors evaluate to false. There could be other design decisions for this choice that I am not aware of, but at the same time, it is a fun oddity that will always surprise beginners without being likely to harm them by chance.