11

Apparently my understanding of the no autovivification pragma is imperfect, as the not-dying-on-line-19 behaviour of the following script is extremely surprising to me.

use 5.014;
use strict;
use warnings;
no autovivification qw(fetch exists delete warn);

{
  my $foo = undef;
  my $thing = $foo->{bar};

  # this does not die, as expected
  die if defined $foo;
}

{
  my $foo = undef;
  do_nothing( $foo->{bar} );

  # I would expect this to die, but it doesn't
  die unless defined $foo;
}

sub do_nothing {
  return undef;
}

Running the script produces:

Reference was vivified at test.pl line 8.

The question: why is $foo autovivified when $foo->{bar} is supplied as an argument to a sub, even though no autovivification is in effect?

ryanm
  • 2,979
  • 18
  • 22
  • Did you install it? Maybe add `warn` to the list of unimports. That would be `no autovivification qw;` and see if there is a warning when it's avoided like the docs say. – simbabque Mar 08 '17 at 09:59
  • It is installed, or else the script would die at line 11. I've updated the question with the results of adding `warn`. – ryanm Mar 08 '17 at 10:12
  • 3
    That's not that surprising. Perl doesn't really know that `do_nothing` does nothing, and since you gave it an argument, it has to autovivify it so you can use it in the sub. In particular, it doesn't know if you do an affectation to `$_[0]` or not in `do_nothing`. – Dada Mar 08 '17 at 10:13
  • That makes sense. It feels like something that could be made clearer in the documentation though, as it's going to be surprising to anyone coming from a pass-by-value language. – ryanm Mar 08 '17 at 10:22
  • There is a critical difference with how it goes in a sub (it's an _lvalue_ context, the object must be modifiable). I think that [this answer](http://stackoverflow.com/a/41401306/4653379) may explain it. – zdim Mar 08 '17 at 10:22
  • But isn't that the whole idea of that module? Simply accessing it should be covered by `fetch`. I would expect that to give `undef` and not autovivify. – simbabque Mar 08 '17 at 10:26
  • @simbabque If perl were pass-by-value that would be true, but arguments are actually passed by reference. Normally the first thing any sub does is make a copy of the values with `my ( $arg ) = @_;`, so it's rarely relevant, but it is the crucial distinction here. As Dada notes the sub could alter `$_[0]`, so there has to be something there to alter - autovivification is unavoidable. – ryanm Mar 08 '17 at 10:39
  • @ryanm You can suppress it with the module -- need `store`. See my answer. – zdim Mar 08 '17 at 10:49

1 Answers1

11

In a subroutine call the arguments to a function are aliased in @_, so it must be possible to modify them. This provides an lvalue context, what will trigger autovivification.

When we look through descriptions of features you use in autovivification, they cover:

  • 'fetch' -- "rvalue dereferencing expressions"
  • 'exists' -- "dereferencing expressions that are parts of an exists"
  • 'delete' -- "dereferencing expressions that are parts of a delete"

None of these deal with lvalues (neither does warn).

To stop autovivification in subroutine calls as well you need to add store

Turns off autovivification for lvalue dereferencing expressions, such as :   [...]

where docs proceed with examples, including subroutine calls.

When I add it to your code,

no autovivification qw(fetch exists delete warn store);
# ...

I get

Reference was vivified at noautoviv.pl line 8.
Reference was vivified at noautoviv.pl line 16.
Died at noautoviv.pl line 19.
zdim
  • 64,580
  • 5
  • 52
  • 81