home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Book HomeLearning Perl, 3rd EditionSearch this book

3.8. Scalar and List Context

This is the most important section in this chapter. In fact, it's the most important section in the entire book. In fact, it wouldn't be an exaggeration to say that your entire career in using Perl will depend upon understanding this section. So if you've gotten away with skimming the text up to this point, this is where you should really pay attention.

That's not to say that this section is in any way difficult to understand. It's actually a simple idea: a given expression may mean different things depending upon where it appears. This is nothing new to you; it happens all the time in natural languages. For example, in English,[83] suppose someone asked you what the word "read"[84] means. It has different meanings depending on how it's used. You can't identify the meaning, until you know the context.

[83]If you aren't a native speaker of English, this analogy may not be obvious to you. But context sensitivity happens in every spoken language, so you may be able to think of an example in your own language.

[84]Or maybe they were asking what the word "red" means, if they were speaking rather than writing a book. It's ambiguous either way. As Douglas Hofstadter said, no language can express every thought unambiguously, especially this one.

The context refers to where an expression is found. As Perl is parsing your expressions, it always expects either a scalar value or a list value.[85] What Perl expects is called the context of the expression.[86]

[85]Unless, of course, Perl is expecting something else entirely. There are other contexts that aren't covered here. In fact, nobody knows how many contexts Perl uses; the biggest brains in all of Perl haven't agreed on an answer to that yet.

[86]This is no different than what you're used to in human languages. If I make a grammatical mistake, you notice it right away, because you expect certain words in places certain. Eventually, you'll read Perl this way, too, but at first you have to think about it.

5 + something  # The something must be a scalar
sort something # The something must be a list

Even if something is the exact same sequence of characters, in one case it may give a single, scalar value, while in the other, it may give a list.[87]

[87]The list may be just one element long, of course. It could also be empty, or it could have any number of elements.

Expressions in Perl always return the appropriate value for their context. For example, how about the "name"[88] of an array. In a list context, it gives the list of elements. But in a scalar context, it returns the number of elements in the array:

[88]Well, the true name of the array @peopleis just people. The @-sign is just a qualifier.

@people = qw( fred barney betty );
@sorted = sort @people; # list context: barney, betty, fred
$number = 5 + @people;  # scalar context: 5 + 3 gives 8

Even ordinary assignment (to a scalar or a list) causes different contexts:

@list = @people; # a list of three people
$n = @people;    # the number 3

But please don't jump to the conclusion that scalar context always gives the number of elements that would have been returned in list context. Most list-producing expressions[89] return something much more interesting than that.

[89]But with regard to the point of this section, there's no difference between a "list-producing" expression and a "scalar-producing" one; any expression can produce a list or a scalar, depending upon context. So when we say "list-producing expressions," we mean expressions that are typically used in a list context and that therefore might surprise you when they're used unexpectedly in a scalar context (like reverse or @fred).

3.8.1. Using List-Producing Expressions in Scalar Context

There are many expressions that would typically be used to produce a list. If you use one in a scalar context, what do you get? See what the author of that operation says about it. Usually, that person is Larry, and usually the documentation gives the whole story. In fact, a big part of learning Perl is actually learning how Larry thinks.[90] Therefore, once you can think like Larry does, you know what Perl should do. But while you're learning, you'll probably need to look into the documentation.

[90]This is only fair, since while writing Perl he tried to think like you do to predict what you would want!

Some expressions don't have a scalar-context value at all. For example, what should sort return in a scalar context? You wouldn't need to sort a list to count its elements, so until someone implements something else, sort in a scalar context always returns undef.

Another example is reverse. In a list context, it gives a reversed list. In a scalar context, it returns a reversed string (or reversing the result of concatenating all the strings of a list, if given one):

@backwards = reverse qw/ yabba dabba doo /;
   # gives doo, dabba, yabba
$backwards = reverse qw/ yabba dabba doo /;
   # gives oodabbadabbay

At first, it's not always obvious whether an expression is being used in a scalar or a list context. But, trust us, it will get to be second nature for you eventually.

Here are some common contexts to start you off:

$fred = something;            # scalar context
@pebbles = something;         # list context
($wilma, $betty) = something; # list context
($dino) = something;          # still list context!

Don't be fooled by the one-element list; that last one is a list context, not a scalar one. If you're assigning to a list (no matter the number of elements), it's a list context. If you're assigning to an array, it's a list context.

Here are some other expressions we've seen, and the contexts they provide. First, some that provide scalar context to something:

$fred = something;
$fred[3] = something;
123 + something
something + 654
if (something) { ... }
while (something) { ... }
$fred[something] = something;

And here are some that provide a list context:

@fred = something;
($fred, $barney) = something;
($fred) = something;
push @fred, something;
foreach $fred (something) { ... }
sort something
reverse something
print something


Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.