2017-03-08 4 views
11

Apparemment, ma compréhension du pragma no autovivification est imparfaite, car le comportement non-mourir-en-ligne-19 du script suivant est extrêmement surprenant pour moi.Autovivification inattendue des arguments

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; 
} 

Exécution du script produit:

Reference was vivified at test.pl line 8. 

La question: pourquoi est $foo autovivified lorsque $foo->{bar} est fourni comme argument à un sous, même si no autovivification est en vigueur?

+0

Avez-vous l'installer? Peut-être ajouter 'warn' à la liste des unimports. Ce serait 'pas d'autovivification qw ;' et voyez s'il y a un avertissement quand il est évité comme le disent les docs. – simbabque

+0

Il est installé, sinon le script va mourir à la ligne 11. J'ai mis à jour la question avec les résultats de l'ajout de 'warn'. – ryanm

+3

Ce n'est pas si surprenant. Perl ne sait pas vraiment que 'do_nothing' ne fait rien, et puisque vous lui avez donné un argument, il doit l'autovivifier pour que vous puissiez l'utiliser dans le sub. En particulier, il ne sait pas si vous faites une affectation à '$ _ [0]' ou pas dans 'do_nothing'. – Dada

Répondre

10

Dans un appel de sous-programme, les arguments d'une fonction sont aliasés en @_, il doit donc être possible de les modifier. Ceci fournit un contexte lvalue, ce qui va déclencher l'autovivification.

Quand nous regardons à travers la description des fonctionnalités que vous utilisez dans autovivification, ils couvrent:

  • 'fetch' - "rvalue expressions déréférencement"
  • 'exists' - « expressions déréférencement qui sont parties d'un existe "
  • 'delete' -" expressions de déréférencement qui font partie d'un supprimer "

Aucun de ces composants ne traite des valeurs lues (ni warn).

Pour arrêter autovivification dans sous-programme appelle aussi bien que vous devez ajouter store

Transforme hors autovivification pour les expressions déréférencement de lvalue, tels que:   [...]

où docs procéder à exemples, y compris les appels de sous-programmes.

Quand je l'ajoute à votre code,

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

Je reçois

 
Reference was vivified at noautoviv.pl line 8. 
Reference was vivified at noautoviv.pl line 16. 
Died at noautoviv.pl line 19.