Que fait `$ hash {$ key} | = {}` en Perl?
-
03-07-2019 - |
Question
Je me débattais avec un Perl qui utilise des références de hachage.
Finalement, il s’est avéré que mon problème était la ligne:
$myhash{$key} |= {};
C’est-à-dire, "attribuez à $ myhash {$ key} une référence à un hachage vide, sauf s’il a déjà une valeur".
Le fait de déréférencer ceci et d’essayer de l’utiliser comme référence de hachage a toutefois entraîné des erreurs d’interpréteur lors de l’utilisation d’une chaîne comme référence de hachage.
Le changer pour:
if( ! exists $myhash{$key}) {
$myhash{$key} = {};
}
... fait fonctionner les choses.
Je n'ai donc pas de problème . Mais je suis curieux de savoir ce qui se passait.
Quelqu'un peut-il expliquer?
La solution
La raison pour laquelle vous voyez une erreur concernant l'utilisation d'une chaîne comme référence de hachage est parce que vous utilisez le mauvais opérateur. | =
signifie "bitwise-or-assign." En d'autres termes,
$foo |= $bar;
est identique à
$foo = $foo | $bar
Ce qui se passe dans votre exemple, c'est que votre nouvelle référence de hachage anonyme est en train de devenir hiérarchisée, puis au niveau du bit-OR avec la valeur $ myhash {$ key}
. Pour compliquer encore les choses, si $ myhash {$ key}
n'est pas défini à ce moment-là, la valeur est la simple chaîne de caractères de la référence de hachage, qui ressemble à HASH (0x80fc284)
. Ainsi, si vous effectuez une inspection superficielle de la structure, elle peut ressembler à une référence de hachage, mais ce n'est pas le cas. Voici quelques sorties utiles via Data :: Dumper
:
perl -MData::Dumper -le '$hash{foo} |= { }; print Dumper \%hash'
$VAR1 = {
'foo' => 'HASH(0x80fc284)'
};
Et voici ce que vous obtenez lorsque vous utilisez le bon opérateur:
perl -MData::Dumper -le '$hash{foo} ||= { }; print Dumper \%hash'
$VAR1 = {
'foo' => {}
};
Autres conseils
Perl a des opérateurs d’affectation abrégés. L'opérateur || =
est souvent utilisé pour définir les valeurs par défaut des variables, car Perl permet aux opérateurs logiques de renvoyer la dernière valeur évaluée. Le problème est que vous avez utilisé | =
qui est un bitwise ou à la place de || =
qui est un logique ou.
À partir de Perl 5.10, il vaut mieux utiliser // =
. //
est l'opérateur défini -ou logique et n'échoue pas dans le coin où la valeur actuelle est définie mais fausse.
Je pense que votre problème était d'utiliser " | =
" (au niveau du bit ou assignation) au lieu de " || =
" (attribuer si faux).
Notez que votre nouveau code n'est pas exactement équivalent. La différence est que " $ myhash {$ key} || = {}
" remplacera les valeurs existantes-mais-fausses par une référence de hachage, mais pas la nouvelle. En pratique, ce n'est probablement pas pertinent.
Essayez ceci:
my %myhash;
$myhash{$key} ||= {};
Vous ne pouvez pas déclarer un élément de hachage dans une clause my
, pour autant que je sache. Vous déclarez d'abord le hachage, puis ajoutez l'élément dans.
Modifier: je vois que vous avez retiré le mon
. Pourquoi ne pas essayer || =
au lieu de | =
? Le premier est idiomatique pour " paresseux " initialisation.