Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Explaining Autovivication

by perly-gates (Initiate)
on Jun 11, 2008 at 22:29 UTC ( #691557=perlquestion: print w/ replies, xml ) Need Help??
perly-gates has asked for the wisdom of the Perl Monks concerning the following question:

I am pretty new to PERL, however I have been programming in other languages for several years (Java, C++). I was wondering what AUTOVIVICATION means?

Comment on Explaining Autovivication
Replies are listed 'Best First'.
Re: Explaining Autovivication
by Joost (Canon) on Jun 12, 2008 at 00:49 UTC
    autovivication basically means that datastructures are automatically expanded at first use.

    For instance, if you've got a hash and access a not previously instantiated element and treat it like a hash reference, a hash reference will be created for you:

    #!/usr/bin/perl -w use strict; my %hash = (); $hash{a}->{b} = 1; print $hash{a}->{b};
    This means you need to do less explicit typing/instantiating, at the cost of possibly accidentally creating structures that aren't there when you mistype.

    Note that perl will still throw an error when you for example treat a hash reference as an array reference, so there's still some checking going on.

Re: Explaining Autovivication
by pc88mxer (Vicar) on Jun 11, 2008 at 23:03 UTC
    Wikipedia has a pretty good explanation: Autovivification.

    Another example:

    $hash->{$x}->{$y} = 1; # with autovivification ( $hash->{$x} ||= {} )->{$y} = 1; # without
Re: Explaining Autovivication
by almut (Canon) on Jun 12, 2008 at 01:59 UTC

    Just another example of where Perl automagically creates data structures as needed:

    #!/usr/bin/perl use strict; use warnings; my $href; # not initialized for my $key (keys %$href) { # ... do something } use Data::Dumper; print Dumper $href; # --> $VAR1 = {};

    which shows that $href has been autovivified to hold a reference to an (empty) hash, simply because you were using the scalar in a way (keys %$href) that would not have worked without such a data structure...

Re: Explaining Autovivication
by planetscape (Chancellor) on Jun 12, 2008 at 10:53 UTC
Re: Explaining Autovivication
by throop (Chaplain) on Jun 12, 2008 at 04:20 UTC
    Autovivification saves a lot of annoying effort. So if $quick is originally empty
    $quick->{brown}->{fox} ->{$jumped} = 1 / $Lazy_dog;
    creates the intermediate hashes so $quick can point to a hash-of-hashes-of-hashes.

    But autovivification can bite you / surprise you, too. If you are testing a value (rather than setting it) autovivification can still add entries to your hash. That is, new keys. E.g., if you start with

    $stateCityPopulation = {Illinois => {Springfield => 116482}, Massachusets => {Springfield => 154082}, Missouri => {Springfield => 150797}}};
    and then you
    foreach my $state (qw(Illinois Massachusets Ohio Missouri)){ my $pop = $stateCityPopulation->{$state}->{Springfield} || next; $springfielders += $pop}
    Now when you look at keys %$stateCityPopulation, 'Ohio' is in there. It's holding an empty array. It was created when you were trying to access the value for $stateCityPopulation->{Ohio}->{Springfield} . Even though you got undef back as a value, the itermediate array got created 'by side effect.'

    If you're debugging code, and you find an array has a bunch of unexpected keys, which hold empty hashes, then autovivification is to blame. If you'd changed the code in the above to

    $pop = ($stateCityPopulation->{$state} && $stateCityPopulation->{$state}->{Springfield}) || next;
    You'd have skipped the autovivification (at the expense of messier code.)

    BTW, if you're debugging a rogue autovivification, the 'w' switch in the debugger is very handy.

    throop

Re: Explaining Autovivication
by ikegami (Pope) on Jun 12, 2008 at 08:41 UTC
    When a scalar ($foo, $foo[$i], $foo{$k}) is undefined and it is used as a reference (@$foo, $foo->[$i], ${$foo}[$i], %$foo, $foo->{$k}, ${$foo}{$k}, $$foo), two things can happen.

    One possibility is that you get a warning. This occurs when you are trying to read from the dereferenced structure. (Technically, when the reference is used as an rvalue).

    >perl -wle"my @x = @$ref; print $ref" Use of uninitialized value in array dereference at -e line 1. Use of uninitialized value in print at -e line 1.

    The other possibility is that the reference is autovivified. That means the appropriate structure (array, hash or scalar) is constructed and a reference to it is stored in the variable. This occurs when you are trying to write to the dereferenced structure. (Technically, when the reference is used as an lvalue).

    >perl -wle"@$ref = my @x; print $ref" ARRAY(0x225228)

    Note then creating an alias to the dereferenced structure is an lvalue, and results in autovivification.

    >perl -wle"sub {}->(@$ref); print $ref" ARRAY(0x225230) >perl -wle"for (@$ref) {} print $ref" ARRAY(0x225228)

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (8)
As of 2015-07-29 11:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (263 votes), past polls