The common misunderstanding in Perl is the difference between :

- A list : (1, 2, 3)
- An array : @my_array containing (1, 2, 3)
- The unary operation coma ‘,’: $operation1, $operation2, $operation3

Perl use the context to act practically over logically. That lead to unexpected behavior if you mislead each of this concept.

The 3 contexts are : void context, list context, scalar context. We will focus on the scalar context here.

First of all, what is the difference between a list and an array, and when the one and the other is used.

When you declare an array :

1 |
my @my_array; |

You can use several function like ‘push’, ‘scalar’ … on it.

You cannot assigned a list to a variable, a list is ephemeral and not operation can be done on it.

You cannot do :

1 |
push (1,2,3), 4 |

It has no meaning. the push (1,2,3), 4 is equivalent to push 1,2,3,4, so push try to push 2, 3, 4 into the constant 1. And that doesn’t work.

Now let show different behavior between all of this concept :

The unary operator :

1 |
my $x = 4, 5, 6; |

Here we have the unary operation coma ‘,’.

To write it more clearly we can do :

1 |
my $x = 4 and 5 and 6; |

So $x = 4 in that case.

The list :

1 |
my $x = (4, 5, 6); |

We use a list in a scalar context. In that case the list will return the last element.

So $x = 6;

The array :

1 2 3 4 |
my $x = @{[4, 5, 6]}; # short for : my @y = (4, 5, 6); my $x = @y; |

We use an array in a scalar context. In that case the array will return the size of the array.

So $x = 3

Now a bit more tricky, the mix of it :

1 |
my $x = @{[4, 5, 6]}, 7; |

The operation assign the array to $x, in that case that mean the size of the array, then execute the constant 7.

So $x = 3

1 |
my $x = (@{[4, 5, 6]}, 7); |

The array in a list context will expand into a list with ’4, 5, 6′ and then we add 7. That create a list with 4, 5, 6, 7.

A list will return the last element in a scalar context.

So $x = 7;

And take care of the unary operator against the list :

1 |
my @x = 4, 5, 6; |

Here we don’t have a list assign to an array, but the unary operator.

So @x = (4).

If you use a list :

1 |
my @x = (4, 5, 6); |

Each element of the list is added to the array.

So @x = (4, 5, 6).

If we are in a function, the behavior is different, always for the practical other logical.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
sub t_unary { return 4, 5, 6; } $x = t_unary(); # $x = 6 sub t_list { return (4, 5, 6); } $x = t_list(); # $x = 6 sub t_array { return @{[4, 5, 6]}; } $x = t_array(); # $x = 3 sub t_mix_unary_array { return @{[4, 5, 6]}, 7; } $x = t_mix_unary_array(); # $x = 7 sub t_mix_list_and_array { return (@{[4, 5, 6]}, 7); } $x = t_mix_unary_array(); # $x = 7 |

The unary operation is transformed into a list before the function return it’s result.

When we mix an array and a list, it result into a list, then the latest result is returned in scalar context.

When we return an array in a scalar context, the result is the size of the array.

We can replace the array return with :

1 2 3 |
sub t_array { return wantarray ? 3 : (4, 5, 6); } |

We cannot generalize the behavior of a function by assuming that a method always return a list except when we return an array.

Each method can have access to the context when we call it and act differently. We often want a function return the most practical result.

The only way to know how a function behave, it to read the documentation on it.

I will show you an example with the “sort_in_place” function :

1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
sub sort_in_place{ my ($t) = @_; if (wantarray()) { # list context return sort @$t } elsif (defined wantarray()) { # in scalar context return scalar(@$t); } else { # in void context @$t = sort @$t; return @$t } } } |

This method check the context. The “wantarray” (badly named), can be used to get the context.

Here the value based on context :

- equal “1″ in a list context.
- equal empty string “” in a scalar context. So wantarray() is false but defined wantarray() is true.
- equal to undef in a void context. So wantarray() and defined wantarray() is false.

So :

In list context :

1 2 3 4 5 |
my @x = (5,4,3); my @y = sort_in_place(\@x); # @x = 5, 4, 3 # @y = 3, 4, 5 |

In scalar context :

1 2 3 4 5 |
my @x = (5,4,3); my $y = sort_in_place(\@x); # @x = 5, 4, 3 # $y = 3 |

In void context :

1 2 3 4 |
my @x = (5,4,3); sort_in_place(\@x); # @x = 3, 4, 5 |

To resume, you have to take care of how you use the context in Perl, and never assume based on your experience that a function behave in a certain way because the array or list behave the same way. You should always check the documentation of the function you use to know how this one behave on different context.

If you have question, or critic, fill free to comment. I will gladly improve this document based on your comments.

I hope it is more clear for you to understand the strange behavior of some functions now.

Celogeek

**Short URL:**http://sck.pm/rghf

You’ve almost got it, but there are several problems.

* You can assign a list to a variable (array or hash). I’m not sure you meant to say that you can’t.

* [1,2,3] is an array reference (a scalar), not an array variable

* defined wantarray is scalar context when wantarray is false. That’s not emphasized in your list.

Thanks Brian.

I have fix the pod doc. So instead of [1,2,3], I have say @my_array containing (1,2,3)

I have add “defined wantarray() is for scalar context only if wantarray() is false.

About the assign to a variable, I have only cover the scalar context. Of course

@x = (1,2,3) will push into @x the value 1,2,3