However, context is not always so obvious. Let's start with a few simple assignment expressions and an example of evaluation of a function.@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
@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)
'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: -EfCdAb-
@string_array = qw (Ab Cd Ef);
print ("-" . reverse(@string_array) . "-");# output: -fEdCbA-
To force an explicit evaluation in a scalar context, you could also write:@a = (reverse("live")); # output: live
$a = (reverse("live"));# output: evil
@a = (scalar(reverse("live"))); # output: evil
@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)
...or more readable:@mc_array = qw(a b c d e);
$size = 5 + @mc_array;# output:10
$size = 5 + scalar(@mc_array); # output:10
'@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.@fruit = qw(apple melon kiwi);
print ("The array 'fruit' is not empty!") if (@fruit);
'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.@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");
}
which is equal to:@numbers = 10 .. 15;
print ((@numbers || 2), "\n");# output:6
Another famous example:print (scalar(@numbers)."\n"); # output:6
@ARG -evaluated in scalar context- returns now the number of arguments (if there are arguments).@ARGV || die "No arguments"
Notice also that the parentheses around the 'scalar idea' is useful!@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");
}
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).$no = 2;
@numbers = ($no);
Why obvious? A list imposes a list context on each of its elements!@numbers = (2, 3, 4);
@all_numbers = (0, 1, @numbers);# output: @all_numbers contains the list (0, 1, 2, 3, 4)
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:#!/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");
}
}
The last three results could bother you. A short explanation:@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)