How does word counting by list assignment work in Perl?

99 Views Asked by At

I cannot exactly understand how the following snippet works:

my $str = 'abc def ghi';
my $num = () = $str =~ /\w+/g;
say $num; # prints the word count, 3

I know that $str =~ /\w+/g returns a list of the words which, apparently, is conveyed to the leftmost assignment. Then $num imposes a scalar context on that list and becomes 3.

But what does () = ('abc', 'def', 'ghi') mean? Is it something like my $a = my @b = (3, 5, 8)? If so, how is the list at the rightmost side transferred to $num at the leftmost side?

2

There are 2 best solutions below

7
ysth On BEST ANSWER

Each perl operator has specific behavior in list and scalar context. Operators give context to their operands, but receive context from what they are an operand to. When a list assignment is placed in scalar context, it returns the number of elements on the right side of the assignment. This enables code like:

while (my @pair = splice(@array, 0, 1)) {

There's nothing special about how = () = is handled; you could just as well do = ($dummy) = or = (@dummy) =; the key part is that you want the match to be list context (producing all the possible matches) and then to just get a count of them.

So you do a list assignment (which is what = does whenever there's either a parenthesized expression or an array or slice as the left operand) but since you don't actually want the values, you can use an empty list. And then place that in scalar context; in this case, using the list assignment as the right operand to a scalar assignment.

1
Boying On

Nowadays fewer people start learning Perl, one of reason is it has some obscure code like your example. Check the perlsecret page for Saturn https://metacpan.org/pod/distribution/perlsecret/lib/perlsecret.pod#Goatse

=( )=

(Alternate nickname: "Saturn")

If you don't understand the name of this operator, consider yourself lucky. You are advised not to search the Internet for a visual explanation.

The goatse operator provides a list context to its right side and returns the number of elements to its left side. Note that the left side must provide a scalar context; obviously, a list context on the left side will receive the empty list in the middle.

The explanation is that a list assignment in scalar context returns the number of elements on the right-hand side of the assignment, no matter how many of those elements were actually assigned to variables. In this case, all the elements on the right are simply assigned to an empty list (and therefore discarded).