5. Context

5.1 What is context?

In human language, a word can have a different meaning, dependent on its context. Study the meaning of the word 'rose' in 'I gave my wife a rose' and in 'I rose from the bench and walked home'.

Perl is context sensitive. It means that the evaluation of an expression or function is dependent of its context. We already met the two most important contexts: scalar context and list context. We'll meet two other contexts: the boolean and void context.
5.1.1 Scalar or list context: assignment expressions
The rule is simple in case of an assignment operator -the equals sign '=' : the expression (scalar of list) on the left side of the assignment operator determines what context the expression(s) on the right side are evaluated in.
@array = EXPRESSION/FUNCTION;  # Expression/function is expected to produce a list which will be assigned to the variable @array.
$scalar = EXPRESSION/FUNCTION; # Expression/function is expected to produce a scalar
However, context is not always so obvious. Let's start with a few simple assignment expressions and an example of evaluation of a function.
@original_copy = @original;  # an array on the left side: list context
$a = @original; # a scalar on the left side: scalar context. The value of $a is the number of elements of @original
($a) = qw(a b c); # a list on the left side: list context. $a is the only element of the list and has the value 'a'
$a = ("a", "b", "c"); # a scalar on the left side: scalar context. $a has the value c (1)
5.1.2 Scalar or list context: the function 'reverse'
Some functions can be evaluated in scalar and list context. A famous example is the function 'reverse'. In list context, 'reverse' reverses the order of its arguments:
@string_array = qw (Ab Cd Ef);
print ("-" , reverse(@string_array) , "-"); # output: -EfCdAb-
'reverse' is expected to return a list, which will be inserted into the list which is passed to print. However, in a scalar context, 'reverse' first concatenates all its arguments, to get a single string, and then reverses that string.
@string_array = qw (Ab Cd Ef);
print ("-" . reverse(@string_array) . "-"); # output: -fEdCbA-
@a = (reverse("live")); # output: live
$a = (reverse("live")); # output: evil
To force an explicit evaluation in a scalar context, you could also write:
@a = (scalar(reverse("live"))); # output: evil

5.2 Evaluating in scalar context: special operators

5.2.1 Concatenation operator
Perl has the . (dot) operator for string concatenation. This operator imposes a scalar context to each of its operands. So, the concatenation operator joins two scalars together.
@mc_array = qw (sebastian daniel florence);
print (@mc_array . "\n"); # scalar context, output: 3
print ((scalar(@mc_array) . "\n")); # explicit scalar context, output: 3
print ("@mc_array", "\n"); # 'print' is now passed a list of arguments (2); output: sebastian daniel florence (and a line break)
5.2.2 Numeric operators like +
Numeric operators join two scalars together.
@mc_array = qw(a b c d e);
$size = 5 + @mc_array; # output:10
...or more readable:
$size = 5 + scalar(@mc_array); # output:10
5.2.3 Conditional operators like 'if'
A list will be evaluated as a scalar in the 'if' statement.
@fruit = qw(apple melon kiwi);
print ("The array 'fruit' is not empty!") if (@fruit);
'@fruit' is evaluated as 'scalar (@fruit)' and returns 3. In the if statement, 3 evaluates to true. So, the print function will run. Evaluating in terms of true or false is called a boolean context, which is in fact a special scalar context.
5.2.4 Comparison operator like '>'
A more complex example:
@numbers = (2, 3, 5, 8, 13, 21, 34);
if( (grep{$_ < 8} @numbers) > 2) {
print ("The array @numbers contains more than 2 numbers lower than 8.\n");
}
'grep' normally returns the list of items that pass the test. Now 'grep' returns the number of successful items in scalar context: the 'greater than' operator ('>') places the 'grep' into scalar context. See 5.3 for clearer code.
5.2.5 Logical operators
Logical operators also provide a scalar Boolean context, i.e. a context that has two values; true or false. Study the next example. The logical or (||) is a scalar operator, so using it will force the evaluation of @numbers to become scalar context.
@numbers = 10 .. 15;
print ((@numbers || 2), "\n"); # output:6
which is equal to:
print (scalar(@numbers)."\n");  # output:6
Another famous example:
@ARGV || die "No arguments"
@ARG -evaluated in scalar context- returns now the number of arguments (if there are arguments).

5.3 Imposing a context explicitly

Avoiding 'context' is for me a better programming strategy. I like code that I can easily read. So, I recommend always using the scalar keyword when imposing a scalar context to an expression. The example of 5.2.4 would for me more readable when written as follows:
@numbers = (2, 3, 5, 8, 13, 21, 34);
if( (scalar(grep{$_ < 8} @numbers) ) > 2) {
print ("The array @numbers contains more than 2 numbers lower than 8.\n");
}
Notice also that the parentheses around the 'scalar idea' is useful!

Assigning a scalar variable to an array could be easily done via:
$no = 2;
@numbers = ($no);
The array @numbers contains a list with the single value 2. The code seems to me better with parentheses around the scalar variable '$no' than without parentheses (which gives the same result by the way).

Sometimes is a context obvious:
@numbers = (2, 3, 4);
@all_numbers = (0, 1, @numbers); # output: @all_numbers contains the list (0, 1, 2, 3, 4)
Why obvious? A list imposes a list context on each of its elements!

5.4 Testing context with wantarray

The function 'wantarray' can be used to test context. Here an easy function 'testcontext' (3) and some tests with the testresults.
#!/usr/bin/perl
use strict;
use warnings;

sub testcontext {
if (wantarray) {
print ("List context (value true)\n");
} elsif (defined wantarray) {
print ("Scalar context (value false)\n");
} else {
print ("Void context (value undef)\n");
}
}

Let's have a look at the function 'testcontext'. The first expression 'if (wantarray)' tests for 'true' or 'false' (boolean context), the second 'if (defined wantarray)' tests for NOT UNDEF (i.e. true or false). If this second test equals false, then the result is UNDEF, which means "unknown value" (4). The function in action:
@array = testcontext(); # List context (value true)
$scalar = testcontext(); # Scalar context (value false)
@array = (1, 2, testcontext()); # List context (value true)
if (testcontext()) {}; # Scalar context (value false)
foreach $i (testcontext()) {}; # List context (value true)
@array = grep { testcontext(); } ("element"); # Scalar context (value false)
@array = map { testcontext(); } ("element"); # List context (value true)
testcontext(); # Void context (value undef)
The last three results could bother you. A short explanation:
  1. A new context is presented: the void context. It is created if the return value of an expression/function is not used or simply UNDEF.
  2. The function 'grep' evaluates -by definition- the expression between curly braces in terms of true and false, i.e. in a boolean, special scalar context (like the conditional 'if').
  3. The function 'map' evaluates -by definition- the expression between curly braces in a list context.

Footnotes
(1) In a scalar context is the comma an operator, evaluating each element from left to the right. The value of the last evaluated element will be returned.
(2) In other words, 'print' imposes list context on its arguments. In 'print (@mc_array . "\n");' the dot operator has a higher precedence than 'print', so @mc_array . "\n" will first be concatenated into a string.
(3) I found the idea in 'Go to Perl 5 Perl schnell und effektiv beherrschen.' by Michael Schilli, Addison-Wesley (1989), p. 53. I've modified the code a little.
(4) A simple test 'if (wantarray)' will not distinguish among undef, zero, the empty string, and "0", which are all equally false. To distinguish between undef and the other values, choose 'if (defined wantarray)'.