Dom Hastings
Dom Hastings

Reputation: 438

Why does Perl create an empty array reference via grep?

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.

Upvotes: 6

Views: 281

Answers (1)

ikegami
ikegami

Reputation: 385764

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

Upvotes: 8

Related Questions