This is a bit embarrassing. I thought I understood dereferencing, but in glancing at a coworke'rs code, I stumbled across an edge case I don't understand. He was using a ternary operator, but instead using it to choose what he's assigning from, he used it to choose what he's assigning to:
# assigning from: my $foo = $bar ? $baz : $quux; # assigning 'to push @{ $row->{close_time} ? \@closed : \@open }, $row;
That surprised me, but it seems reasonable. But then he also pointed out that taking a reference to the arrays is not necessary:
push @{ $row->{close_time} ? @closed : @open }, $row;I thought that @{} would dereference the contained expression. The following script further illustrates my confusion:
#!/usr/bin/perl use strict; use warnings; use Data::Dumper; my ( @open, @closed ); my $open = 1; push @{ $open ? @open : @closed } => 'boo!'; push @{ $open ? \@open : \@closed } => 'boo!'; print Dumper( \@open ); push @{ @{ @{ @{ @{@open} } } } } => ['bar']; print Dumper(\@open);
That prints:
$VAR1 = [ 'boo!', 'boo!' ]; $VAR1 = [ 'boo!', 'boo!', [ 'bar' ] ];
I've been using @{} and similar constructs for so long that I can't even remember where they are documented. perlref says:
Anywhere you'd put an identifier (or chain of identifiers) as part of a variable or subroutine name, you can replace the identifier with a BLOCK returning a reference of the correct type. In other words, the previous examples could be written like this:
$bar = ${$scalarref}; push(@{$arrayref}, $filename); ${$arrayref}[0] = "January"; ${$hashref}{"KEY"} = "VALUE"; &{$coderef}(1,2,3);
That suggests that the block is supposed to return a reference, but clearly it's not required Is this documented behavior?
Cheers,
Ovid
New address of my CGI Course.
In reply to Misunderstanding dereferencing by Ovid
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |