| Previous | Table of Contents | Next |
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? Heres the catch: You cant use any user-defined variablesjust $_ and @ARGV.
Which movie do you want to see?
Which movies do you want to see?
Each of these questions expects a different answer. The first expects a single moviea scalar. The second question expects a list of moviesan 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 lets 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. Thats 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. (Thats what you want because $array[3] is the last element of a four-element array. Remember: Perl arrays have zero-based indexing.)
Some operations dont merely act differently depending on the context; they create the context for you. Thats 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 doesnt 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. Thats 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.
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 youd expect.
But look:
@list = (1, 4, 6, 10, 15); print scalar(@list);
prints 5.
Congratulations! Now that youve covered the basics of Perl syntax, you know enough to write useful programs in Perl. Dont worry if everything isnt crystal clearit doesnt need to be. As long as you understand how conditional statements and loops work, and understand the differences between scalars and arrays, youre well prepared for Chapter 2.
@x = (2, 9, 5); print 3 + (4, 1, 2) + @x;
@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, ; }
0 1 0 1 2 3
0 1 2 3 0 1
0 1 2 3 0 1 2 3
0 1 2 3 7 10 5 2
($a, $b) = ((1, 2), 3); print a is $a and b is $b.;
| Previous | Table of Contents | Next |