Ovid has asked for the wisdom of the Perl Monks concerning the following question:

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.

Replies are listed 'Best First'.
Re: Misunderstanding dereferencing
by davorg (Chancellor) on Jan 11, 2007 at 11:43 UTC

    Some old discussion on the same topic. Looks like it's a well-known bug that everyone is too scared to fix :-)

    As meryln says in that thread:

    an array name is sometimes automatically a reference to that array, even though the language definition would argue otherwise
    --
    <http://dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

      Looks like it's a well-known bug that everyone is too scared to fix
      Looks like its been fixed in bleed:
      $ cat /tmp/p #!/usr/bin/perl @a = qw(1 2 3); @b = qw(a b c d); push @{ $x ? @a : @b }, 'foo'; print "a: @a\n"; print "b: @b\n"; print "3: @3\n"; print "4: @4\n"; __END__ $ ./perl /tmp/p a: 1 2 3 b: a b c d 3: 4: foo

      Dave.

        I see no error so I'm wondering what is the behaviour now. Does it push 'foo' to the array @4 (@b evaluated in scalar context) ?

        Edit: sorry I didn't read to the bottom of your code...

        Edit2: more sincerity

      Thank you. Glad to know I wasn't being a total idiot in getting confused on that one.

      Cheers,
      Ovid

      New address of my CGI Course.