Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Perl create an empty array reference via grep?

Tags:

perl

I may be missing something obvious, but I'm at a loss as to why the following Perl creates an array reference via grep, but not sort or another general reference?

print @$arr; # no output
print ref $arr; # no output
print scalar @$arr; # no output
print ref $arr; # no output
print sort @$arr; # no output
print ref $arr; # no output
print grep { 0 } @$arr; # no output
print ref $arr; # ARRAY

I'm probably missing something obvious, or maybe it's just one of those things, but it stumped me and I wondered if anyone knew the answer...

I've tested this on Perl 5.8 and 5.10 and get the same behaviour on both.

like image 931
Dom Hastings Avatar asked Aug 28 '14 13:08

Dom Hastings


People also ask

What happens when a nonexistent element of an array is referenced in Perl?

When you request a non-existent element from an array, you get undef back. Save this answer.

How to check if an array is empty in Perl?

A simple way to check if an array is null or defined is to examine it in a scalar context to obtain the number of elements in the array. If the array is empty, it will return 0, which Perl will also evaluate as boolean false.


1 Answers

The interesting question is why don't any of the others. Dereferencing in lvalue context will autovivify the operand if it's undef.

$ perl -E'@$arr = "b"; say $arr // "[undef]"'
ARRAY(0x335b558)

Arguments are always passed by reference to subs, so they are evaluated in lvalue context.

$ perl -E'sub f { }  f( @$arr ); say $arr // "[undef]"'
ARRAY(0x284e9f8)    

But the "functions" in perlfunc are actually operators, and as such, they get to invent their own syntax and calling conventions. Perl knows that sort won't modify its operands when using the default compare function, so it doesn't evaluate them in lvalue context.

$ perl -E'sort @$arr; say $arr // "[undef]"'
[undef]

grep aliases $_ to each item passed to it, so it its arguments can be modified (even though that's usually not a good idea), so its arguments are evaluated in lvalue context.

$ perl -E'@a = "a"; grep { $_ = uc($_) } @a; say @a'
A
like image 113
ikegami Avatar answered Sep 28 '22 17:09

ikegami