Question

Pourquoi le travail d'extrait suivant du tout? Et quel mal pourrait être possible avec cela? Mais sérieusement, est-il une raison quelconque, le code se ${} évalué à tous et ensuite utilisé comme référence scalaire?

use strict;
no strict 'refs';

our $message = "Hello world!";
print "${ lc 'MESSAGE' }\n";
Était-ce utile?

La solution

Il est ok, sauf si vous utilisez des références symboliques . Supposons que le code suivant:

my %messages = (hello => "Hello world!", bye => "Bye-bye, world!");
sub get_message_ref { return \$messages{$_[0]} }; # returns scalarref
print "${ get_message_ref('bye') }\n";

D'accord, son utilité est pas évident avec scalarrefs, mais il est très utile avec arrayrefs.

print "keys: @{[keys %messages]}\n";

Autres conseils

Nous expliquons en détail dans Perl intermédiaire.

La syntaxe générale pour les recherches variables est:

 SIGIL  BLOCK  INDEXY-THING

Pour un scalaire simple qui ressemble à:

 print $   { foo };

Vous avez probablement vu cela quand vous avez besoin de séparer un nom de variable des choses qui l'entourent:

 print "abc${foo}def\n";

Si vous avez juste un identifiant Perl dans le bloc et pas de gâchis autour, vous pouvez laisser hors les accolades, ce qui est le cas commun:

 print $foo;

Cependant, cela est la même chose pour déréférencer une référence:

 SIGIL  BLOCK-RETURNING-REFERENCE  INDEXY-THINGS

Si la chose que vous obtenez dans le bloc est une référence, Perl tente de déréférencer comme vous demande aussi:

 my $ref = \ '12345';
 print $     { $ref };

C'est un vrai bloc cependant, et pas seulement le sucre. Vous pouvez avoir autant de déclarations que vous le souhaitez là:

 print $     { my $ref = \ '1234'; $ref };

Maintenant, vous n'êtes pas seulement spécifier un identifiant Perl, Perl ne suppose pas que vous lui donner un identifiant et il exécute le code et utilise le résultat comme référence. Tenez compte de la différence entre ces déclarations de say presque identiques:

    use 5.010;
our $foo = "I'm the scalar";

sub foo { \ "I'm the sub" }

say ${foo};
say ${foo;};

Dans ce second say Perl voit le point-virgule, se rend compte qu'il est pas un identifiant, interprète le code à l'intérieur des accolades sous forme de texte, et renvoie le résultat. il utilise depuis le résultat est une référence, le ${...} à déréférencer. Peu importe où vous faites cela, afin que vous le faites dans une chaîne entre guillemets n'est pas spécial.

Remarquez aussi la our là. C'est important maintenant que vous allez envisager quelque chose d'un peu plus compliqué:

    use 5.010;
our $foo = "I'm the scalar";

sub foo { \ "I'm the sub" }
sub baz { 'foo' }

say ${foo};
say ${foo;};
say ${baz;};

Perl intreprets cette dernière say code et voit le résultat est une référence; c'est la simple chaîne foo. Perl voit que ce n'est pas une référence, mais il est maintenant dans un contexte déréférencement il fait une référence symbolique (comme Greg Bacon décrit ). Étant donné que les références symboliques travaillent avec des variables dans la table des symboles, que $foo devait être une variable de package.

Comme il est facile de gâcher ça, strict a un contrôle à portée de main pour cela. Toutefois, lorsque vous l'éteignez, ne soyez pas surpris quand il vous mord. :)

De la "Utilisation des références" section de la documentation perlref :

  

Où que vous mettiez un identifiant (ou une chaîne d'identifiants) en tant que partie d'un nom de variable ou sous-programme, vous pouvez remplacer l'identifiant d'un bloc de retour d'une référence du type correct. En d'autres termes, les exemples précédents pourraient être écrits comme ceci:

$bar = ${$scalarref};
push(@{$arrayref}, $filename);
${$arrayref}[0] = "January";
${$hashref}{"KEY"} = "VALUE";
&{$coderef}(1,2,3);
$globref->print("output\n");  # iff IO::Handle is loaded
     

Certes, il est un peu ridicule d'utiliser les Curlies dans ce cas, mais le bloc peut contenir toute expression arbitraire, en particulier, indicés expressions:

&{ $dispatch{$index} }(1,2,3);    # call correct routine
     

En raison de pouvoir omettre les Curlies pour le cas simple de $$x, les gens font souvent l'erreur de considérer le déréférencement comme les opérateurs appropriés, et je me demande au sujet de leur priorité. Si elles étaient, cependant, vous pouvez utiliser des parenthèses au lieu d'accolades. Ce n'est pas le cas. Considérez la différence ci-dessous; affaire 0 est une version courte à la main du boîtier 1, et non pas le cas 2:

$$hashref{"KEY"}   = "VALUE";     # CASE 0
${$hashref}{"KEY"} = "VALUE";     # CASE 1
${$hashref{"KEY"}} = "VALUE";     # CASE 2
${$hashref->{"KEY"}} = "VALUE";   # CASE 3
     

Cas n ° 2 est aussi trompeur que vous accédez à une variable appelée %hashref, sans déréférencer par $hashref le hachage, il est sans doute le référencement. Ce serait le cas 3.

Plus tard dans "références symboliques":

  

Nous avons dit que les références à l'existence comme il naît nécessaire si elles ne sont pas définis, mais on n'a pas dit ce qui se passe si une valeur utilisée comme référence est déjà défini, mais pas une référence difficile. Si vous l'utilisez comme référence, il sera traité comme une référence symbolique. Autrement dit, la valeur du scalaire est le nom d'une variable, au lieu d'un lien direct vers un (peut-être) valeur anonyme.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top