48 votes

Quand devrais-je utiliser la et pour appeler un sous-programme Perl?

J'ai entendu dire que les gens ne devraient pas utiliser & d'appel Perl sous-marins, j'.e:

function($a,$b,...);
# opposed to
&function($a,$b,...);

Je sais que pour une seule la liste des arguments est optionnelle, mais ce sont des cas où il est approprié d'utiliser le & et les cas où vous devez absolument ne pas l'utiliser?

Aussi comment ne l'augmentation de performance sont en jeu lorsque l'omission de la &?

52voto

brian d foy Points 71781

Je suis fréquemment agresseur d' &, mais surtout parce que je suis en train de faire bizarre interface de trucs. Si vous n'avez pas besoin d'une de ces situations, ne pas utiliser de l' &. La plupart de ces ne sont là que pour accéder à une définition de sous-programme, de ne pas appeler une sous-routine. Tout est dans perlsub.

  1. En prenant une référence à un sous-programme nommé. C'est probablement la seule commune de la situation pour la plupart des Perlers:

     my $sub = \&foo;
    
  2. De même, l'affectation à un typeglob, ce qui vous permet d'appeler le sous-programme avec un nom différent:

     *bar = \&foo;
    
  3. Vérifier la présence d'un sous-programme est défini, comme vous pouvez vous en suites de test:

     if( defined &foo ) { ... }
    
  4. Suppression d'une définition de sous-programme, qui ne devrait pas être commun:

     undef &foo;
    
  5. Fournir un répartiteur de la sous-routine dont le seul travail est de choisir le bon sous-programme à appeler. C'est la situation que je utiliser & d' appeler une sous-routine, et quand je m'attends à appeler le répartiteur de nombreuses fois, et la nécessité de presser un peu le rendement de l'opération:

     sub figure_it_out_for_me {
        # all of these re-use the current @_
          if( ...some condition... ) { &foo     } 
       elsif( ...some other...     ) { &bar     }
       else                          { &default }
       }
    
  6. Sauter dans une autre sous-routine à l'aide de l'argument courant de la pile (en remplacement de l'actuelle sous-routine dans la pile d'appel), un unrare opération de distribution, en particulier en AUTOLOAD:

     goto ⊂
    

Il y a quelques endroits où vous pourriez utiliser, mais il ya de meilleures façons:

  1. Pour appeler un sous-programme avec le même nom qu'un Perl intégré. Il suffit de ne pas avoir de sous-programmes avec le même nom qu'un Perl intégré. Vérifier perlfunc pour voir la liste de noms que vous ne devriez pas les utiliser.

  2. Pour désactiver les prototypes. Si vous ne savez pas ce que cela signifie ou pourquoi vous voulez, ne pas utiliser l' &. Un peu de magie noire code pourriez avoir besoin d'elle, mais dans ces cas, vous savez probablement ce que vous êtes en train de faire.

  3. Déréférencer et d'exécuter un sous-programme de référence. Utilisez simplement l' -> de la notation.

36voto

chaos Points 69029

OMI, le seul moment où il n'y a aucune raison pour l'utiliser & est si vous êtes l'obtention ou l'appel d'une coderef, comme:

sub foo() {
    print "hi\n";
}

my $x = \&foo;
&$x();

L'heure principale que vous pouvez utiliser qui vous absolument ne devrait pas , dans la plupart des cas est lorsque l'appel d'un sous c'est un prototype qui spécifie une valeur d'appel de comportement. Ce que je veux dire par là, c'est que certains prototypes permettent de réinterprétation de la liste d'arguments, par exemple la conversion d' @array et %hash spécifications pour les références. Donc le sub va être attendent ces réinterprétations eu lieu, et, sauf si vous revenez à ce que les longueurs sont nécessaires pour imiter à la main, le sous obtiendrez entrées très différentes de celles qu'il attend.

Je pense principalement les gens essaient de vous dire que vous êtes toujours écrit en Perl 4 style, et nous avons un beaucoup plus propre, plus belle chose que l'on appelle Perl 5 maintenant.

Concernant les performances, il y a différentes façons de Perl optimise sous les appels qui & de défaites, avec l'un des principaux étant d'inlining de constantes.

Il y a aussi une circonstance où l'utilisation d' & offre un avantage de performance: si vous transférez un appel sous avec foo(@_). À l'aide de &foo est infiniment plus rapide que l' foo(@_). Je ne le recommande pas, sauf si vous avez définitivement trouvé par profilage que vous avez besoin que les micro-optimisation.

18voto

cms Points 2500

La sous-routine() forme désactive le prototype de la vérification. Cela peut ou peut ne pas être ce que vous voulez.

http://www.perl.com/doc/manual/html/pod/perlsub.html#Prototypes

Prototypes vous permettent de spécifier le nombre et le type de votre sous-routine arguments, et ont été vérifiées au moment de la compilation. Cela peut fournir des informations utiles d'aide au diagnostic.

Les Prototypes ne s'appliquent pas aux appels de méthode, ou les appels effectués à l'ancienne de style à l'aide de l' & préfixe.

Le & est nécessaire pour faire référence ou de déréférencement d'un sous-programme ou code de référence

par exemple

sub foo {
   # a subroutine
}

my $subref = \&foo; # take a reference to the subroutine

&$subref(@args);  # make a subroutine call using the reference.

my $anon_func = sub { ... }; # anonymous code reference
&$anon_func(); # called like this

Protypes ne sont pas applicables à la sous-routine références soit.

La sous-routine formulaire est également utilisé dans la soi-disant magie goto forme.

L'expression goto &subroutine , remplace l'appel de contexte avec un appel au sous-programme nommé, à l'aide de la valeur actuelle de @_.

En essence, vous pouvez passer d'un appel à une sous-routine avec un appel à l'nommé un. C'est une pratique courante dans de chargement automatique de blocs, où un différé sous-programme appel peut être fait, peut-être avec quelques modifications à @_ , mais il semble pour le programme entièrement comme si c'était un appel à l'nommé sous.

par exemple

sub AUTOLOAD {
    ...
    push @_, @extra_args; # add more arguments onto the parameter list
    goto &subroutine ; # change call another subroutine, as if we were never here
}

}

voir l' explication détaillée de cette technique ici

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X