Beefy Boxes and Bandwidth Generously Provided by pair Networks Joe
Welcome to the Monastery
 
PerlMonks  

Comment on

( #3333=superdoc: print w/ replies, xml ) Need Help??
"You will be miserable until you learn the difference between scalar and list context"

Programming Perl 3rd ed, page 69

An introduction to context

Context is everywhere in Perl. Every operand is evaluated in some context. Every operator imposes a context to its operands. Every expression is constrained by the context in which it is evaluated.

The two main contexts are scalar context and list context. Another is void. An operator that works on scalars imposes a scalar context. You can tell which kind of context an operator has by checking the standard Perl documentation. Every operator that creates a list context for its operands has "LIST" in its syntactic description.

Context matters because operands in Perl can behave differently according to context. This is sort of like overloading. A function (or other expression) can provide different results depending on the context it's in.

Context in action

For these examples, I'll use localtime since it's a common function which evaluates differently according to context. In a list context, it returns a series of numeric values that describe the current time. In a scalar context, it returns a human readable string to describe the current time.

# Example 1. # @now will be (40, 51, 20, 9, 0, 109, 5, 8, 0) @now = localtime(); # Example 2. # $now will be "Fri Jan 9 20:51:40 2009" $now = localtime();

In example 1, we assign localtime to an array, which imposes a list context. The array takes in all the values returned by localtime.

In example 2, localtime is assigned to a scalar, which imposes a scalar context. In that context, localtime returns the string, "Fri Jan 9 20:51:40 2009".

You can try this yourself on the command line. If you're on a Windows box, you can run the code in Example 1 like this:

perl -e "@now = localtime(); for $now(@now) {print $now;}" 432351301092120 perl -e "$now = localtime(); print $now;" Tue Jan 13 05:26:30 2009

If you're on a Unix-like operating system (like Linux or newer Macs), replace the double quotes above with single quotes.

Now, back to context.

# Example 3. # $sec will be 40, $min will be 51, $hr will be 20 ($sec,$min,$hr) = localtime();

In example 3, localtime is assigned to a list expression which has three scalar variables in it (wrapped in parentheses). Because of the list expression, localtime() is in list context. The three variables get the first three values from the list that localtime() returns, and its other return values are discarded.

Note that this assignment is also to a list expression:

my ($x) = localtime(); # Example 4

To write it without the list context, drop the parentheses.

my $x = localtime(); # Example 5

Other common occurrences of context

When creating a hash, the elements are in list context. This probably doesn't do what's intended:

# BAD! [Example 6] my %h = ( now => localtime() );

Instead, localtime needs scalar to force it to be a single value associated with the key. There's more about scalar later in this tutorial.

# GOOD [Example 7] my %h = ( now => scalar localtime() );

If you want to have the list returned from localtime in an array in the hash, an anonymous array reference is the best way to do that.

# GOOD [Example 8] my %h = ( now => [ localtime() ] );

If you're not familiar with references, see perlreftut, perlref, and References quick reference.

The arguments to a call to a user-defined sub are in list context also.

# Example 9 sub print_time { my $now = shift @_; print "The time is now $now\n"; } # prints "The time is now 40" print_time( localtime() ); # prints "The time is now Tue Jan 13 05:26:30 2009" print_time( scalar localtime() );

There is a way for a user-defined function to have its arguments in a scalar context, but that's seldom used, often discouraged, and outside the scope of this tutorial. Most of the time, subs' arguments are in list context.

Perl's built-ins don't follow this rule at all. Example 10 does not do what's intended.

# Example 10 my @loc = ($offset, $length); my $part = substr( $string, @loc );

Perl's substr takes only scalar arguments. Putting some of those arguments into an array this way won't work. (The above is equivalent to "substr( $string, 2 )" because @loc is in scalar context.)

Context propagates into sub calls

When control reaches a return, the operand to the right of that return finds itself in the context that the sub was in when it was called. That means that in the following code, localtime is in the list context from print.

print clock(); # Example 11 sub clock { return localtime(); }

A sub's calling context might come from some operator high up in the call stack.

Forcing scalar context

If you want to force a scalar context on an operand, use scalar. For example:

print scalar localtime(); # Example 12

When you print, its operands are in list context. It accepts a list of values to be printed. If you just "print localtime()", it will print something like "40512090109580" (the list of values all stuck together), but "scalar localtime()" looks like "Fri Jan 9 20:51:40 2009".

Forcing list context

To force a list context where there wouldn't be one otherwise, assign to an empty list.

my $match_count = ()= /x/g; # Example 13

The "/x/g" in scalar context would match only once, but with the list context, it finds every match. The value of "()=" in scalar context is the number of items in the list.

Void context

Void context is a special case of scalar context. It's the context of something that doesn't have an operator working on it. The value of a thing in void context is discarded, not used for anything. For example, the body of a while loop is in void context.

# Example 14 while (<>) { ponder( $_ ); # void context }

The only way void context is like scalar context is that it's not list context. The only way void context is not like scalar context is that some things in void context can generate warnings that they wouldn't generate in a scalar context.

Determining context with wantarray

A sub can determine what context it was called in by using wantarray. If the sub is in list context, wantarray will return a true value. In scalar context, it returns a false value that's defined. In void context, it will return undef.

# Example 15 sub print_context { if ( wantarray() ) { print "list\n"; } elsif ( defined wantarray() ) { print "scalar\n"; } else { print "void\n"; } } print_context(); ()= print_context(); scalar print_context(); __END__ void list scalar

More flavors of scalars

The Camel book subdivides scalar context into numeric, string, and don't care context, but it's more useful to think of these as casts.

Scalar assignment is a "don't care" because numbers and strings are treated the same—passed through to the scalar variable to have and to hold just as they are. Another "don't care" cast is boolean because strings and numbers aren't converted when being interpreted as true or false. To learn more about how values are treated in boolean context, see True or False? A Quick Reference Guide

In numeric and string contexts, a variable might undergo a transformation from one to the other in order to facilitate the workings of the operator. In example 16, a string is cast to a number to accommodate the numeric operation of the postfix "--" operator.

# Example 16 my $beer_inventory = '99 bottles'; print "how much beer? $beer_inventory\n"; $beer_inventory--; # take one down... print "how much beer? $beer_inventory\n"; __END__ how much beer? 99 bottles how much beer? 98

To force an expression to a string, use "''." (that is, append to an empty string). To interpret an expression as a number, use "0+" (that is, add zero). It's better to use "0+" than some other identity function (such as "1*") because that's what overload uses to designate the numeric cast. To force a boolean interpretation, use "!!" (that is, boolean negation twice).

# Example 17 my $s = "12 monkeys"; my $n = 31337; my $stringified = ''. $n; # "31337" my $numified = 0+ $s; # 12 my $boolean = !! $n; # 1

Every cast is possible. Strings can be cast to numbers or booleans. Numbers can be cast to strings or booleans. Booleans can be cast to numbers or strings.

Context clash

A single value (such as a scalar) in a list context becomes a list with one item.

# Example 18 my $scaley = 'snake'; my @listy = $scaley; # does the same thing: #my @listy = ('snake');

That's simple enough. What about the other way around? In scalar context, a list of expressions separated by commas evaluates to the whatever the last item evaluates to in scalar context. A slice of an array or hash in scalar context will similarly evaluate to the last element in the slice (for more on slices, see Slices).

# Example 19 my @t = ( 'one', 'two' ); my $x = ( 'one', 'two' ); # 'two' my $y = @t[0,1]; # 'two' my $z = ( 'larry', 'moe', @t[0,1] ); # 'two' my $r = ( 'larry', 'moe', @t ); # 2 my $f = ( 'old', 'man', localtime() ); # "Fri Jan 9 20:51:40 2009"

Other things ordinarily used in list context have their own special scalar context behaviors. One particularly useful one is demonstrated by the $r value in example 19. An array in scalar context evaluates to the number of items in the array. For a list of others, see On Scalar Context.

Interpolative context

This isn't a full fledged context like scalar and list context, but it helps to know in which places variables are expanded (interpolated) into their values. For a full list of these, see Quote and Quote-like Operators. For a brief example, see below.

# Example 20 my $friend = 'Perl'; my $literal = '$friend'; # literally, '$friend' my $expanded = "$friend"; # literally, 'Perl'

To reiterate, this isn't a context the way "scalar context" is a context, and it isn't what we normally mean when we say simply "context." Still, it may help to think of it as a context when one is considering interpolation. For the full scoop including many other places this is relevant, see the full documentation (Quote and Quote-like Operators).

More context

If the deep dark magic of wantarray leaves you wanting for more, look into Want and Contextual::Return, which are advertised to detect contexts I have not mentioned here. Also, look at overload for creating an object which can interpret itself differently in numeric and string contexts.

Another good source of information about context is What is Scalar Context? by Dominus.

Thanks to belg4mit, tye, theorbtwo, Arunbear, bart, zentara, ikegami, Limbic~Region, Narveson, jdporter, moritz, Porculus, ww, gwadej, oshalla, and gwadej for commenting on an earlier draft!


In reply to Context tutorial by kyle

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • Outside of code tags, you may need to use entities for some characters:
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Chatterbox?
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others studying the Monastery: (13)
    As of 2014-04-23 10:40 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      April first is:







      Results (541 votes), past polls