Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

No autovivification, for loop aliasing, lvalue vs rvalue in for loops

by leszekdubiel (Scribe)
on Sep 02, 2016 at 10:48 UTC ( #1171041=perlquestion: print w/replies, xml ) Need Help??

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

I turned off autovivification in my code, but for loops broke that and my hashes got populated with unwanted data.

For loops do aliasing, and array is created to be aliased... But I really don't understand my code works despite reading documentation. Could anyone explain why @{$$n{'x'}} throws exception outside loop, and is accepted inside loop (see code below), and why square brackets make so much difference to autovivification?

#!/usr/bin/perl -CSDA use utf8; use strict; use warnings; no warnings qw{uninitialized numeric}; no autovivification; # qw{fetch exists delete store}; use Data::Dumper; print "\n\ninitialize data structures, no autovivification\n"; my $n = { a => [1, 2 ], b => [3, 4], }; $$n{'x'}{'y'}{'z'} and die; $$n{'x'}{'y'}[0] and die; $$n{'x'}{'y'} and die; $$n{'x'} and die; print "so far, so good, no 'x' autovivified:\n"; print Dumper $n; # "Can't use an undefined value as an ARRAY reference": # @{$$n{'x'}} and die; print "\n\nnow the same but in loop:\n"; for my $e (@{$$n{'x'}}) { } print "why 'x' autovivified?\n"; print Dumper $n; print "\n\nnow the same but in loop:\n"; for my $e (@{[ $$n{'y'} ]}) { } print "why 'y' NOT autovivified?\n"; print Dumper $n; 1;

Here comes the output of this program:

initialize data structures, no autovivification so far, so good, no 'x' autovivified: $VAR1 = { 'a' => [ 1, 2 ], 'b' => [ 3, 4 ] }; now the same but in loop: why 'x' autovivified? $VAR1 = { 'x' => [], 'a' => [ 1, 2 ], 'b' => [ 3, 4 ] }; now the same but in loop: why 'y' NOT autovivified? $VAR1 = { 'x' => [], 'a' => [ 1, 2 ], 'b' => [ 3, 4 ] };

Replies are listed 'Best First'.
Re: No autovivification, for loop aliasing, lvalue vs rvalue in for loops
by LanX (Cardinal) on Sep 02, 2016 at 11:37 UTC
    > and why square brackets make so much difference to autovivification?

    this

    for my $e (@{[ $$n{'y'} ]}) { }

    has no possible autovivification. It copies the list within [] and translates to

    for my $e (@{[ undef ]}) { }

    Nota Bene: there is a fundamental difference between \@a and [@a] !

    While both are array refs, only the first one keeps a link to @a while the latter is only an anonymous copy.

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!

Re: No autovivification, for loop aliasing, lvalue vs rvalue in for loops
by LanX (Cardinal) on Sep 02, 2016 at 12:06 UTC
    >
    # "Can't use an undefined value as an ARRAY reference": # @{$$n{'x'}} and die; print "\n\nnow the same but in loop:\n"; for my $e (@{$$n{'x'}}) { } print "why 'x' autovivified?\n"; print Dumper $n;

    Well you get right the same effect without disabling autovivification.

    While it feels like autovivification there's IMHO technically an aliasing/for-loop magic happening. This is probably not covered by the internal autovivification mechanisms (i.e. explicitely accessing sub-elements) and hence was forgotten.

    Not sure if it's easy to implement, but you should commit a bug report to raise the question.

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!

      Ok -- I will file a bug on that. Thank you.
        Why I stop autovivification... I am processing information about manufacturing mirrors in our company (dubielvitrum.pl), and two hashes are compared and during that comparison they are modified. I don't want hash to be modified when I just look for values in it. Another reason is I want to have warnings when I try to write on deep levels on such hashes, because this means error quite often.
Re: No autovivification, for loop aliasing, lvalue vs rvalue in for loops
by ikegami (Pope) on Sep 03, 2016 at 05:00 UTC
    no autovivification;

    is short for

    no autovivification qw( fetch exists delete );

    However, the list values of the foreach loop is evaluated in lvalue context so the loop body can alter (store values into) the resulting variables.

    $_ = uc($_) for @a;

    As such, you need

    no autovivification qw( fetch exists delete store );
    $ perl -e' use Data::Dumper; { no autovivification qw( fetch exists delete ); my $h; for (@{ $h->{k} }) { } print(Dumper($h)); } { no autovivification qw( fetch exists delete store ); my $h; for (@{ $h->{k} }) { } print(Dumper($h)); } ' $VAR1 = { 'k' => [] }; Can't vivify reference at a.pl line 14.
Re: No autovivification, for loop aliasing, lvalue vs rvalue in for loops
by stevieb (Canon) on Sep 02, 2016 at 13:31 UTC

    Just out of sheer curiosity, what is your purpose/reasoning behind wanting to disable autoviv? Is it just playing around, or do you have a legit use-case for doing this? If you do, I'd like to hear about it.

Re: No autovivification, for loop aliasing, lvalue vs rvalue in for loops
by leszekdubiel (Scribe) on Sep 04, 2016 at 08:19 UTC

    I have filed a bug: https://rt.perl.org/Ticket/Display.html?id=129177

    Minimal code for reproduce is:

    ##### use Data::Dumper;$Data::Dumper::Indent=0; my $n = {}; for (@{$n->{'x'}}) { print 1; } print Dumper ($n), "\n"; ##### Output: ##### $VAR1 = {'x' => []}; ##### # the same throws exception: # Can't use an undefined value as an ARRAY reference @{$$n{'y'}} and print 2;

    Explanation is (these are citations of perl gurus) :

    The documentation of autovivification in the core distribution is clearly less than satisfactory. By consulting four different doc files (as well as the CPAN autovivification documentation), have pieced together the following explanation which should be treated as a *provisional, layperson's* explanation of the phenomenon. The documentation is somewhat adequate in explaining why array and hash elements autovivify when they do, but -- as you have probably found out already -- quite inadequate in explaining why autovivification does *not* happen where you might expect it to.
    So here goes.
    Perl autovivifies intermediate elements in data structures when it senses that you need to use the lowest elements in such structures as *storage locations*. In Perl, a storage location is referred to as an *lvalue* (where the 'l' refers to the customary 'left-hand side' or an assignment). The context in which you are assigning a value to a storage location -- or when Perl senses that you are about to assign a value to a storage location -- is referred to as *lvalue context*. When you need to assign a value to an array or hash element that doesn't already exist, Perl will create that elements -- and any elements needed to reach that element -- for you. More formally, when you are in lvalue context, perl will autovivify data structures as needed.

    The possibility of making foreach refrain from autovivification when possible has been raised before (i.e., it would be considered a bug fix), but it has been put off indefinitely because it would cause a significant slowdown.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1171041]
Approved by Corion
Front-paged by LanX
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (3)
As of 2020-11-25 04:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?