snapsvg

2014-12-11

Day 11: List context and parentheses

It's common to start off believing that () make a list, or create list context. That's because you normally see lists first explained as constructing arrays:

my @array = (1,2,3);

and therefore it looks like the parentheses are part of list context.

They aren't. Context in this statement is determined by the assignment operator. All the parentheses are doing is grouping up those elements, making sure that all the , operators are evaluated before the = is.

There is exactly one place in the whole of Perl where this common misconception is actually true.

LHS of =

On the left of an assignment, parentheses create list context. This is how the Saturn operator works.

$x = () = /regex/g;
#   |______________|

The marked section is an empty list on the left-hand side of an assignment operator: the global match operation is therefore in list context.

LHS of x

This is a strange one. The parentheses do construct a list, but the stuff inside the parentheses does not gain list context.

my @array = (CONSTANT) x $n;

In this case, CONSTANT - presumably sub CONSTANT {...} - is in list context; x gains list context from the =, and CONSTANT inherits it.

my $str = (CONSTANT) x $n;

Here we have x in scalar context because of $str, and CONSTANT in scalar context because of that. This is not really a whole lot of use, however.

Various Contexts

This sub reports whether it's called in scalar, list or void context1:

sub sayctx { say qw(scalar list void)[wantarray // 2] }

Now we can test a few constructs for context:

# void
sayctx;

# scalar
scalar sayctx;

# scalar
my $x = sayctx;

# list
my @x = sayctx;

# list
() = (sayctx) x 1;

# scalar
my $x = (sayctx) x 1;

# list
last for sayctx;

# scalar
while (sayctx) { last }

# scalar
1 if sayctx;

# scalar, void
sayctx if sayctx;

# scalar, scalar
sayctx > sayctx;

1 Understanding it is left as an exercise to the reader.

No comments:

Post a Comment