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

Interesting behaviour this afternoon. The following code runs OK and prints 'Bar' only.

my $ref; foreach (@$ref) { print "Foo\n"; } print "Bar\n";

But try to assign that non-existent list to another variable and use that ...

my $ref; foreach (my @list = @$ref) { print "Foo\n"; } print "Bar\n";

... and Perl says Use of uninitialized value in array dereference at foo.pl in line 5. Can someone explain why the extra assignment causes an error?

--t. alex
but my friends call me T.

Replies are listed 'Best First'.
(tye)Re: Uninitialized or not?
by tye (Sage) on Nov 27, 2002 at 18:20 UTC

    I suspect that the first case is considered "left-hand context", that is, potentially "being assigned to", which triggers autovivification while the second case is purely "right-hand context" (just getting the value) and so doesn't trigger autovivication.

    This makes some sense since you can assign to $_ inside of the foreach, but I'm not a big fan of the way it works.

    I'd rather just have an option like strict that just turns off all autovivification (it requires a bit more careful coding but can also catch certain types of coding errors for you -- and I prefer that style of coding, it making the intent clearer).

    Update: How did you get the impression that I was proposing anything other than that, Aristotle? strict is disabled by default. "turns off" also implies that autovification being "on" would be the default.

            - tye
      Autovivification is very handy on occasion - but can get in the way also. Seeing as the very most of the time I want the DWIM behaviour (sometimes I outright rely on it), I'd prefer this stricture to be off by default but available to whomever wants to enable it on a scope-by-scope basis (exists $key{doesnt_exist}{this_neither} comes to mind).

      Makeshifts last the longest.

Re: Uninitialized or not?
by pg (Canon) on Nov 27, 2002 at 18:19 UTC
    • In your first case, you are actually testing foreach's tolerance with undef, and it is just fine. You can even do:
      foreach (undef) { }
      Although it is meaningless.
    • In you second case, you are testing assignment's (=) tolerance with undef, and it is a NO.

      Hmm, disagree. According to your comment,

      foreach (undef) { print "foo\n"; }

      does nothing (well, you said 'meaningless') .. when in fact it prints out 'foo' once, since 'undef' can be interpreted as an array with a single calue, 'undef'.

      --t. alex
      but my friends call me T.
Re: Uninitialized or not?
by Aristotle (Chancellor) on Nov 27, 2002 at 18:16 UTC
    Blind guess and baseless intuition: I suspect it's because of the aliasing behaviour of for, while assigning causes Perl to attempt an actual copy.

    Makeshifts last the longest.

Re: Uninitialized or not?
by demerphq (Chancellor) on Nov 27, 2002 at 19:37 UTC
    As tye says this is an example of autovivification at work. And furthermore the timing is interesting as just the other day Nick Clark started a thread on p5p about this. He (and I) believe that autovivification should be made more consistent. However not the direction that tye suggest, rather the opposite. Anyway the thread is here.

    --- demerphq
    my friends call me, usually because I'm late....

      That is not the opposite direction. I want an option.

      What would make sense would be to separate 'use strict "refs"' into two options, one for symbolic references and one for undefined references, so you could ignore errors from $u->[0] without having to autovivify (the difference being whether you want simply evaluating $u->[0] to set $u -- I can see wanting to ignore that error, but I don't see much point in having simple evaluation silently setting things).

      Add to this an option to disable autovivification in left-hand context and we'd all be happy.

              - tye
        Well, i can see your idea about strict being useful for sure. But for me the one thing id like to see is that @{undef} returns 0 or () in a rhs context and not throw an error. If I have to twiddle an option then fine. If that means it gets autovivified then thats fine too. Although id prefer that things dont get autovivified on read. Even multilevel accesses.

        :-)

        --- demerphq
        my friends call me, usually because I'm late....