Being clever by half may hurt

ferreira on 2008-04-25T12:10:40

I know Perl may be quite irregular sometimes, and because it is irregular gotchas are easily glossed over and bite.

After some code refactoring, I ended up with a code like that:

for (@$x) {
    push @array, $_;
}

which immediately suggested me an equivalent expression:

push @array, @$x;

Unfortunately, this is not quite equivalent when $x is undef. Under strict, @$x bails with "Can't use an undefined value as an ARRAY reference " while for (@$x) {} works flawlessly as a loop that is never entered. So the real equivalence I was looking for is:

if ( $x ) {
    push @array, @$x;
}

whick is ok (as long as $x contains array refs or undefs).


Re:

izut on 2008-04-25T18:25:47

You can also:

push @array, @{ $x || [] };

It is not pretty, but anyway :-)

Re:

Aristotle on 2008-04-26T00:32:02

If $x is not a long and complex expression, then readability would command to use push @array, @$x if $x;.

Note that the really equivalent code would be this:

$x = [] if not defined $x;
push @array, @$x;

Or in 5.10 parlance:

push @array, @{ $x //= [] };

Because the reason that the for loop doesn’t throw an error is that it because it aliases $_ to each element, rather than copying, it has to provide lvalue context on each iteration, which means it must also provide lvalue context to the container expression – and an undef in any lvalue context autovivifies.