views:

715

answers:

3

What is the difference between the scalar and list contexts in Perl and does this have any parallel in other languages such as Java or Javascript?

A: 

This simply means that a data-type will be evaluated based on the mode of the operation. For example, an assignment to a scalar means the right-side will be evaluated as a scalar.

I think the best means of understanding context is learning about wantarray. So imagine that = is a subroutine that implements wantarray:

sub = {
  return if ( ! defined wantarray ); # void: just return (doesn't make sense for =)
  return @_ if ( wantarray ); # list: return the array
  return $#_ + 1; # scalar: return the count of the @_
}

The examples in this post work as if the above subroutine is called by passing the right-side as the parameter.

As for parallels in other languages, yes, I still maintain that virtually every language supports something similar. Polymorphism is similar in all OO languages. Another example, Java converts objects to String in certain contexts. And every untyped scripting language i've used has similar concepts.

nicerobot
The question is about scalar/list *context* not scalar/array *variables*. The concept is AFAIK unique to Perl.
Michael Carman
Yea, i misunderstood the question. Edited.
nicerobot
Better. I'd un-down-vote if I could but SO tells me that it's "too old."
Michael Carman
+11  A: 

Various operators in Perl are context sensitive and produce different results in list and scalar context.

For example:

my(@array) = (1, 2, 4, 8, 16);
my($first) = @array;
my(@copy1) = @array;
my @copy2  = @array;
my $count  = @array;

print "array: @array\n";
print "first: $first\n";
print "copy1: @copy1\n";
print "copy2: @copy2\n";
print "count: $count\n";

Output:

array: 1 2 4 8 16
first: 1
copy1: 1 2 4 8 16
copy2: 1 2 4 8 16
count: 5

Now:

  • $first contains 1 (the first element of the array), because the parentheses in the my($first) provide an array context, but there's only space for one value in $first.
  • both @copy1 and @copy2 contain a copy of @array,
  • and $count contains 5 because it is a scalar context, and @array evaluates to the number of elements in the array in a scalar context.

More elaborate examples could be constructed too (the results are an exercise for the reader):

my($item1, $item2, @rest) = @array;
my(@copy3, @copy4) = @array, @array;

There is no direct parallel to list and scalar context in other languages that I know of.

Jonathan Leffler
thanks. i like your example, except for one minor nit: if you had populated your array with values other than 1,2,3 then the value of $copy2 would have been some other number than 3 and it would not have been confused with the size of the array itself. i was confused at first. but u explained. np.
Fair point - I'll fix it.
Jonathan Leffler
I think that it would be clearer if you changed $count to $copy1, @copy1 to @copy2 and $copy2 to $count. Then the variable names would match the contents.
Mr. Muskrat
The variable naming leaves much to be desired. I'll rework: $count -> $first; $copy1 -> $acopy; $copy2 -> $count.
Jonathan Leffler
Yes. Thanks again.
+4  A: 

Scalar context is what you get when you're looking for a single value. List context is what you get when you're looking for multiple values. One of the most common places to see the distinction is when working with arrays:

@x = @array;  # copy an array
$x = @array;  # get the number of elements in an array

Other operators and functions are context sensitive as well:

$x   = 'abc' =~ /(\w+)/;  # $x = 1
($x) = 'abc' =~ /(\w+)/;  # $x = 'abc'
@x   = localtime();       # (seconds, minutes, hours...)
$x   = localtime();       # 'Thu Dec 18 10:02:17 2008'

How an operator (or function) behaves in a given context is up to the operator. There are no general rules for how things are supposed to behave.

You can make your own subroutines context sensitive by using the wantarray function to determine the calling context. You can force an expression to be evaluated in scalar context by using the scalar keyword.

In addition to scalar and list contexts you'll also see "void" (no return value expected) and "boolean" (a true/false value expected) contexts mentioned in the documentation.

Michael Carman
I like your "other operators" examples, especially the notable behavior of the =~ operator in scalar and list contexts. I would not have guessed that behavior.
Yes, in scalar context =~ tells you whether or not something matched. In list context it returns a list containing the captured text.
Michael Carman