Section 3.7. Scalar and List Context


3.7. 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. It wouldn't be an exaggeration to say that your entire career in using Perl will depend upon understanding this section. If you've gotten away with skimming the text up to this point, this is where you should pay attention.

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

[*] 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.

[] 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 a scalar or list value.[*] What Perl expects is called the context of the expression.[]

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

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

If something is the exact same sequence of characters, in one case it may give a single, scalar value, and in another, it may give a list.[] Expressions in Perl always return the appropriate value for their context. For example, how about the "name[§] 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:

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

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

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

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[**] return something more interesting than that.

[**] 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 might surprise you when they're used unexpectedly in a scalar context (like reverse or @fred).

3.7.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. A big part of learning Perl is learning how Larry thinks.[] Therefore, once you can think like Larry does, you know what Perl should do. But while youre learning, you'll probably need to look into the documentation.

[] 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 if an expression is being used in a scalar or a list context. But, trust us, it will become 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 and not a scalar one. The parentheses are significant here, making the fourth of those different than the first. 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.

Let's look at other expressions you've seen and the contexts they provide. First, here are some that provide scalar context to something:

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

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

3.7.2. Using Scalar-Producing Expressions in List Context

Going this direction is straightforward: if an expression doesn't normally have a list value, the scalar value is automatically promoted to make a one-element list:

     @fred = 6 * 7; # gets the one-element list (42)     @barney = "hello" . ' ' . "world";

Well, there's one possible catch:

     @wilma = undef; # OOPS! Gets the one-element list (undef)       # which is not the same as this:     @betty = ( );    # A correct way to empty an array

Since undef is a scalar value, assigning undef to an array doesn't clear the array. The better way to do that is to assign an empty list.[*]

[*] Well, in most real-world algorithms, if the variable is declared in the proper scope, you will not need to empty it explicitly. This type of assignment is rare in well-written Perl programs. You'll learn about scoping in the next chapter.

3.7.3. Forcing Scalar Context

On occasion, you may need to force scalar context where Perl is expecting a list. In that case, you can use the fake function scalar. It's not a true function because it just tells Perl to provide a scalar context:

     @rocks = qw( talc quartz jade obsidian );     print "How many rocks do you have?\n";     print "I have ", @rocks, " rocks!\n";        # WRONG, prints names of rocks     print "I have ", scalar @rocks, " rocks!\n"; # Correct, gives a number

Oddly enough, there's no corresponding function to force list context. It turns out you never need it. Trust us on this, too.



Learning Perl
Learning Perl, 5th Edition
ISBN: 0596520107
EAN: 2147483647
Year: 2003
Pages: 232

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net