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

If I try running the following:

#!/usr/bin/perl -w use Data::Dumper; { my $hashref; $hashref->{'foo'} = "bar"; print Dumper($hashref); }
then I get the expected result:
[alex@home dev]$ perl -w hashref.pl $VAR1 = { 'foo' => 'bar' };
However, if I try to combined the my and the assignment on the same line, as in the following:
#!/usr/bin/perl -w use Data::Dumper; { my $hashref->{'foo'} = "bar"; print Dumper($hashref); }
then Perl gives me an error:
[alex@home dev]$ perl -w hashref2.pl Can't use an undefined value as a HASH reference at hashref2.pl line 6 +.
This seems odd to me -- does this mean that there's a limit to what autovivification will do?

The difference seems semantic to me. Please, pass me a clue by four.

Alex / talexb / Toronto

"Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds

Replies are listed 'Best First'.
Re: Using an undefined value as a hashref
by itub (Priest) on Sep 09, 2005 at 21:13 UTC
    The trick is that variables created by "my" are not available until the next statement, as documented in perlsub:
    The declared variable is not introduced (is not visible) until after the current statement. Thus, my $x = $x; can be used to initialize a new $x with the value of the old $x, and the expression my $x = 123 and $x == 123 is false unless the old $x happened to have the value 123 .

      I don't think that's totally true. The variable name is not available until the next statement, but the variable itself is. Otherwise, I don't see how the following two statements would work:

      open(my $fh, ...); read($fh, my $buf='', ...);

      I think the problem here is that you can't auto-vivify the lvalue returned by my. Can anyone confirm or deny any of this?

        I'd guess it is because my returns the generated variable.

        Ordinary morality is for ordinary people. -- Aleister Crowley

      Wow.

      Thank you. I didn't know that. I've learned a new thing today. Cool.

      Alex / talexb / Toronto

      "Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds

Re: Using an undefined value as a hashref
by NetWallah (Canon) on Sep 09, 2005 at 21:44 UTC
    Here is a trick to achieve your desired results at a cost of 5 more bytes ...
    (my $hashref={})->{'foo'} = 'bar';
    The initial assignment to {} could, of course, be replaced by an existing hash ref.

         "Man cannot live by bread alone...
             He'd better have some goat cheese and wine to go with it!"

Re: Using an undefined value as a hashref
by InfiniteLoop (Hermit) on Sep 09, 2005 at 21:00 UTC
    The correct usage is:
    #!/usr/bin/perl -w use Data::Dumper; { my $hashref = {'foo' => "bar"}; print Dumper($hashref); }
    Refer to my for more details.

      Thanks, but that's not my point.

      I'm trying to assign a value to an element of a hash, and I want to pass around a hashref. So I really do want to set the foo element of hashref to the value bar. And Perl will let me do that if I predeclare the hashref and then set the value, but I can't do it all in one shot.

      I didn't realize that, and spent some time trying to track down the problem -- so now I'd like to understand what part of Perl syntax I misunderstand. Or what black hole I just fell into.

      Alex / talexb / Toronto

      "Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds

Re: Using an undefined value as a hashref
by ambrus (Abbot) on Sep 09, 2005 at 21:58 UTC

    Wow! Nice catch. This has tought me again that lvalues are more often present in perl than you'd think and that you have to take care of their strange effects.

Re: Using an undefined value as a hashref
by runrig (Abbot) on Sep 09, 2005 at 21:19 UTC
    my accepts a single variable or a list of variables as argument(s), not array elements or slices.
      my accepts a single variable or a list of variables as argument(s), not array elements or slices.
      Yes, but is it really a function, or does it just appear to behave like a function when you look at it sideways? (It does have a return value, but that's usually thrown away -- and does it behave the same way every time?)

      Since my has both compile-time and run-time aspects, it's more of a convenience that you can actually do things like

      my $x = 42;
      If Perl were instead a little stricter in partitioning compile actions vs. execution, then my might be defined as a compiler directive:
      my $x; my ($y,@z);
      It's intentional laziness that we can initialize these variable declarations in the same statement. Even more so when non-constants like this work:
      my @args = @_; my $x = $x; my @results = `some | funky | shell | result`;
      We run into problems with my and its cousins because they gloss over some of the bookkeeping and other administrivia that we normally don't care to keep up with. When we try and make them do more work than they can, we find feechers that don't DWIM.

      -QM
      --
      Quantum Mechanics: The dreams stuff is made of