
Perl has a special kind of scalar context called boolean context — this context occurs inside of conditional expressions (if and while conditions for example) and applies to the arguments of logical operator. In such a context, an expression is evaluated in scalar context and then a truth value (true or false) is determined from the result of that expression.
So, for example, if we want to exit the program with a usage message if no command line arguments were given:
die usage("No arguments given") unless @ARGV;
(of course, I am assuming a function named ‘usage’ exists and produces a relevant message). This tests the @ARGV array in a boolean scalar context — and recall that when an array is evaluated in a scalar context it returns its size. So, if @ARGV is empty, the result is 0 which is false and so we die() with an appropriate message. Another example might be to test if an array (or any list) has a certain number of some particular entry — we can use grep() to test a condition:
my @list = (12, 14, 101,102,103, 104, 4);
if( (grep{$_ > 100} @list) > 3) {
print "More than 3 items greater than 100\n";
}
Normally, grep() returns the list of successful elements, but in scalar context it returns the number of successful elements. The greater than operator places the grep() into scalar context, and that result is compared to 3. Logical operators also provide a scalar boolean context to their operands:
@ARGV || die "No arguments";
Here the @ARGV array is again evaluated in scalar boolean context, so if it contains anything the OR expression is ignored (logical short circuit evaluation), otherwise the left hand side is false and the die() is then called.
Another, very different, kind of context sometimes causes people problems — that is, operator context. Perl variables are not typed according to what kind of data they hold, but operators are associated with particular types of data (numerical or string operators) and Perl will convert data to the appropriate type for the given operator:
if(21 < 200) {print "True\n"} # true
if(21 lt 200) {print "True\n"} # false
In the second example above the string operator ‘lt’ (less than) is used so Perl converts 21 to "21" and 200 to "200" and compares them according to ascii collating sequence (asciibetical order). The string "21" is greater than the string "200". Such conversion works the other way around as well:
if( "14" gt "9"){print "True\n"} # false
if( 14 > 9) {print "True\n"} # true
As a final warning, converting a number to a string is simple — the string is just the character representation of the number. However, converting strings to numbers isn’t always as clear. For example, how should the string "xyz" be converted? The rule is: if a string begins with something that looks like a number (ignoring any leading whitespace) then convert to the equivelant number, ignoring any non-numeric characters that might follow the number. Otherwise, the numeric value of a string is 0:
my $a = 14; # $a is: 14
$a .= 5; # $a is: "145"
my $b = "Hello World";
$a .= $b; # $a is: "145Hello World"
$a += 5; # $a is: 150
$a += $b; # $a is: 150
Here we first set $a to the number 14, then we concatenated it (a string operation) with 5 (so Perl converts the 14 and the 5 to strings and concatenates them into the string "145"). We set $b to just a string and then concatenate with $a giving us a string in $a that starts with a number. When add 5 to $a Perl converts the string "145Hello World" into the number 145 and then adds 5 to it. Lastly, if we try to add $a with the string in $b, Perl treats $b as a number and it evaluates to 0, so $a is left as 150.
If you run that whole last example with warnings turned on (you do run with the -w switch right?) you’ll notice two warnings about using a string in a numeric context. It is easy to mistakenly use a string comparison operator instead of a numeric one (or vica versa), and using warnings will often tell you when you’ve made such a questionable comparison.
*****