Previous Table of Contents Next


Exercise 7

Difficulty: Hard

Write a short program that accepts an arbitrary number of numbers on the command line and prints all the even ones. Sound easy? Here’s the catch: You can’t use any user-defined variables—just $_ and @ARGV.

Session 8
Contexts

“Which movie do you want to see?”

“Top Gun”

“Which movies do you want to see?”

“Top Gun,” “Cocktail,” “Risky Business”

Each of these questions expects a different answer. The first expects a single movie—a scalar. The second question expects a list of movies—an array. The questions are the same; the contexts are different (Figure 1-13).


Figure 1-13  Contexts

Every Perl operation is evaluated in a particular context. There are two major contexts: scalar and array. Some Perl operations act differently depending on the context, yielding an array in an array context and a scalar in a scalar context. This sounds awfully abstract, so let’s look at some examples.

@array = (1, 3, 6, 10);
@new_array       = @array;

The = operator sees the array on its left, and so copies all of @array.

$length_of_array = @array;

The = operator sees the scalar on its left, and so copies the number of elements into it.

(That last statement should set off a warning bell: The left-hand side and right-hand side are different types. That’s not necessarily an error, but it does mean that something strange is going to happen.)

When an array is evaluated in a scalar context by certain operations (e.g. =, or <, or ==), it “becomes” the number of elements in the array. So this will iterate through @array:

for ($i=0; $i < @array; $i++)

When you see an expression like $i < @array, you should ask yourself, “Is that comparison occurring in a scalar context or an array context?” Because < wants to compare two numbers, @array is evaluated in a scalar context, returning the length of the array. So if there are four elements in @array, $i starts at 0 and stops at 4. (That’s what you want because $array[3] is the last element of a four-element array. Remember: Perl arrays have zero-based indexing.)

Some operations don’t merely act differently depending on the context; they create the context for you. That’s why you often have to look at both sides of the operator as well as the operator itself to determine what happens.

$b = (4, 5, 6)

performs the assignment in a scalar context, setting $b to the last element: 6.

@array = (4, 5, 6);
$b = @array;

also performs the assignment in a scalar context, but setts $b to 3, the number of elements.

@b = (4, 5, 6)

performs the assignment in an array context, setting @b to (4, 5, 6).

($a, $b, $c) = (4, 5, 6)

also uses an array context, setting $b to 5.

The + operator creates a scalar context, but that doesn’t tell you everything you need to know: Does + convert arrays to scalars by using the length? Or does it use the last element? See for yourself.

4 + (100)

is 104.

4 + (25, 200);

is 204.

print() creates an array context. That’s why

print “abc”, “def”, (“ghi”, “jkl”)

prints abcdefghijkl.

Consider

print 4 + (25, 200);

which prints 204, because the + sees only the last element of (25, 200). Compare that to these statements, which might look like they should do the same thing.

@x = (25, 200);
print 4 + @x;

prints 6, since the + operator uses a scalar context in which @x evaluates to the number of elements. The difference is very subtle, but worth remembering: some operations distinguish betwen an array (such as @x) and a mere list of elements (such as (25, 200)). And all of this happens before print() gets a chance to interpret @x in an array context.

The scalar() Function

Sometimes you want an expression to be evaluated as a scalar, even though Perl might want to evaluate it as an array. You can force a scalar context with the scalar() function.

@list = (1, 4, 6, 10, 15);
print “@list”;

prints 1 4 6 10 15, as you’d expect.

But look:

@list = (1, 4, 6, 10, 15);
print scalar(@list);

prints 5.

Congratulations! Now that you’ve covered the basics of Perl syntax, you know enough to write useful programs in Perl. Don’t worry if everything isn’t crystal clear—it doesn’t need to be. As long as you understand how conditional statements and loops work, and understand the differences between scalars and arrays, you’re well prepared for Chapter 2.

Quiz 8

1.  What context is used for the expression 4 + (8, 9)?
a.  Scalar, because + always expects two scalars.
b.  Scalar, because 4 is a scalar.
c.  Array, because + expects one scalar on each side.
d.  Array, because (8, 9) is an array.
2.  What’s printed by the following statements?
@x = (2, 9, 5);
print 3 + (4, 1, 2) + @x;
a.  8
b.  9
c.  10
d.  11
3.  What’s printed by the following program? (Caution—this is tricky!)
@array = (7, 10, 5, 2);
for ($i = 0; $i < @array;        $i++) { print $i, ‘ ’; }
print “\n”;
for ($i = 0; $i < (7, 10, 5, 2); $i++) { print $i, ‘ ’; }
a.  
0 1
0 1 2 3
b.  
0 1 2 3
0 1
c.  
0 1 2 3
0 1 2 3
d.  
0 1 2 3
7 10 5 2
4.  What’s printed by the following statements? (Caution—this is tricky too!)
($a, $b) = ((1, 2), 3);
print “a is $a and b is $b.”;
a.  a is 1 and b is 2
b.  a is 2 and b is 3
c.  a is 2 and b is
d.  a is 2 and b is 2


Previous Table of Contents Next