2010-08-03 3 views
19

À partir de Perl 5.10, il est maintenant possible d'étendre lexicalement la variable de contexte $_, soit explicitement my $_;, soit dans une construction given/when.

Est-ce que quelqu'un a trouvé de bonnes utilisations du lexical $_? Cela rend-il les constructions plus simples/plus sûres/plus rapides?

Qu'en est-il des situations que cela rend plus compliqué? Est-ce que le $_ lexical a introduit des bogues dans votre code? (puisque les structures de contrôle qui écrivent à $_ utiliseront la version lexicale si elle est dans la portée, cela peut changer le comportement du code s'il contient des appels de sous-programme (en raison de la perte de portée dynamique)

Finalement, Je voudrais construire une liste qui clarifie quand utiliser $_ comme un lexical, comme un global, ou quand ce n'est pas grave du tout.


NB: que de perl5-5.24 ces fonctionnalités expérimentales sont no longer part of perl.

+0

Je pense que la réponse à votre question est essentiellement couverte [ici] (http://stackoverflow.com/questions/3393038/does-my-do-anything-if-is-implied) dans la réponse à ma question. – xenoterracide

+0

@xenoterracide => La réponse à cette question couvre certainement certains des aspects du '_ _ 'lexicaux, mais pas tous. Voilà ce que je voudrais couvrir ici. –

+0

Je sais mais pourrait aussi bien avoir un bon endroit pour commencer;) – xenoterracide

Répondre

8

IMO, une grande chose à sortir de lexical $_ est le nouveau symbole du prototype _.

Ceci vous permet de spécifier un sous-programme de sorte qu'il prenne un scalaire ou si aucun n'est fourni, il saisira $_.

Ainsi, au lieu d'écrire:

sub foo { 
    my $arg = @_ ? shift : $_; 

    # Do stuff with $_ 
} 

Je peux écrire:

sub foo(_) { 
    my $arg = shift; 

    # Do stuff with $_ or first arg. 
} 

Pas un grand changement, mais il est juste que beaucoup plus simple quand je veux que le comportement. L'enlèvement de la plaque chauffante est une bonne chose.

Bien sûr, cela a pour effet de changer les prototypes de plusieurs builtins (par exemple chr), ce qui peut casser du code. Dans l'ensemble, je souhaite la bienvenue à lexical. Il me donne un outil que je peux utiliser pour limiter la confusion des données accidentelles et les interactions bizarres entre les fonctions. Si je décide d'utiliser $_ dans le corps d'une fonction, en le lexicalisant, je peux être sûr que quel que soit le code que j'appelle, $_ ne sera pas modifié dans le code appelant.

La portée dynamique est intéressante, mais pour la plupart je veux une portée lexicale. Ajoutez à cela les complications autour de $_. J'ai entendu des avertissements terribles au sujet de l'imprévu de simplement faire local $_; - qu'il est préférable d'utiliser for ($foo) { } à la place.Lexicalized $_ me donne ce que je veux 99 fois sur 100 quand j'ai localisé $_ par tous les moyens. Lexical $_ rend une grande fonctionnalité de commodité et de lisibilité plus robuste.

Le gros de mon travail a dû travailler avec perl 5.8, donc je n'ai pas eu la joie de jouer avec le $_ lexical dans les grands projets. Cependant, il semble que cela ira un long chemin pour rendre l'utilisation de $_ plus sûre, ce qui est une bonne chose.

+2

Quelles raisons ont été données pour 'for ($ foo) {...}' plutôt que 'local * _ = \ $ foo;'? Dans mon expérience, ce dernier est un peu plus rapide (puisqu'il n'a pas besoin de configurer une portée et un itérateur pour la liste des éléments individuels), mais je serais intéressé s'il y a des problèmes de sécurité à garder à l'esprit. –

+1

Eric, je suis allé chercher la référence spécifique aujourd'hui et je ne l'ai pas trouvé. Tout ce que je peux me rappeler à ce stade est un avertissement contre «local $ _» venant d'une «personne dont je respecte l'opinion» à la mi-2009. Ainsi, à moins que je puisse mieux justifier la réclamation, mieux l'ignorer comme rien de plus que par ouï-dire. L'affirmation était que la localisation ne couvrait pas tous les cas de bord avec le «$ _» spécial. Je n'ai jamais trouvé de rapport de bogue ou de cas de test pour sauvegarder l'avertissement. – daotoad

0

N'ont eu aucun problème ici, bien que j'ai tendance à suivre quelque peu une politique "Ne demandez pas, ne dites pas" quand il s'agit de la magie Perls. C'est à dire. les routines ne sont pas habituellement devrait s'appuyer sur leurs pairs visser avec des données non lexicales comme effet secondaire, ni les laisser.

J'ai testé le code sur diverses versions de Perl 5.8 et 5.10, tout en utilisant un 5.6 décrivant Camel pour référence occasionnelle. N'a eu aucun problème. La plupart de mes affaires ont été faites à l'origine pour perl 5.8.8.

3

Une fois, j'ai trouvé un issue (bug serait trop fort d'un mot) qui est apparu lorsque je jouais avec le module Inline. Ce script simple:

use strict qw(vars subs); 
for ('function') { 
    $_->(); 
} 
sub function { 
    require Inline; 
    Inline->bind(C => <<'__CODE__'); 
void foo() 
{ 
} 
__CODE__ 
} 

échoue avec un message d'erreur Modification of a read-only value attempted at /usr/lib/perl5/site_perl/5.10/Inline/C.pm line 380.. Profondément dans les internes du module Inline est un sous-programme qui voulait modifier $_, conduisant au message d'erreur ci-dessus.

En utilisant

for my $_ ('function') { ... 

ou déclarant contraire my $_ est une solution viable à ce problème.

(Le module Inline a été corrigé pour résoudre ce problème particulier).

1

[Justification: Une réponse courte avec un résumé rapide pour les nouveaux arrivants Perl qui peuvent passer. Lorsque vous cherchez "perl lexical topic" on peut finir ici.]

Maintenant (2015) Je suppose qu'il est de notoriété publique que l'introduction du sujet lexical (my $_ et certaines fonctionnalités connexes) a conduit à certains difficiles à détecter à le début des comportements involontaires et ainsi était marked comme experimental, puis entré dans un deprecation stage.


Résumé partiel de#RT119315: Une suggestion a été quelque chose comme use feature 'lextopic';to make use of a new lexical topic variable: $^_. Un autre point soulevé était qu'un "implicit name for the topicalizing operator ... other than $_" fonctionnerait mieux lorsqu'il est combiné avec des fonctions lexicales explicites (par exemple lexical map ou lmap). Si ces approches permettrait en quelque sorte de récupérer given/when n'est pas clair. Dans l'au-delà des phases expérimentales et d'amortissement, il se peut que quelque chose finisse par vivre dans la rivière du CPAN.

Questions connexes