Cosa fa `$ hash {$ key} | = {}` in Perl?
-
03-07-2019 - |
Domanda
Stavo lottando con alcuni Perl che usano riferimenti hash.
Alla fine si è scoperto che il mio problema era la linea:
$myhash{$key} |= {};
Cioè, " assegnare $ myhash {$ key} un riferimento a un hash vuoto, a meno che non abbia già un valore " ;.
Dereferenziare questo e provare a usarlo come riferimento hash, tuttavia, ha comportato errori dell'interprete sull'uso di una stringa come riferimento hash.
Modificandolo in:
if( ! exists $myhash{$key}) {
$myhash{$key} = {};
}
... ha fatto funzionare le cose.
Quindi non ho un problema . Ma sono curioso di sapere cosa stesse succedendo.
Qualcuno può spiegare?
Soluzione
Il motivo per cui visualizzi un errore sull'uso di una stringa come riferimento hash è perché stai utilizzando l'operatore sbagliato. | =
significa " bit a bit o assegna. " In altre parole,
$foo |= $bar;
è uguale a
$foo = $foo | $bar
Quello che sta succedendo nel tuo esempio è che il tuo nuovo riferimento hash anonimo viene sottoposto a stringenza, quindi bit-ORed con il valore di $ myhash {$ key}
. Per confondere ulteriormente le cose, se $ myhash {$ key}
non è definito al momento, il valore è la semplice stringa del riferimento hash, che assomiglia a HASH (0x80fc284)
. Quindi, se fai un'ispezione superficiale della struttura, potrebbe apparire come un riferimento hash, ma non lo è. Ecco alcuni utili risultati tramite Data :: Dumper
:
perl -MData::Dumper -le '$hash{foo} |= { }; print Dumper \%hash'
$VAR1 = {
'foo' => 'HASH(0x80fc284)'
};
Ed ecco cosa ottieni quando usi l'operatore corretto:
perl -MData::Dumper -le '$hash{foo} ||= { }; print Dumper \%hash'
$VAR1 = {
'foo' => {}
};
Altri suggerimenti
Perl ha operatori di assegnazione abbreviata. L'operatore || =
viene spesso utilizzato per impostare valori predefiniti per le variabili grazie alla funzione Perl di far restituire l'ultimo valore valutato agli operatori logici. Il problema è che hai usato | =
che è un bit per bit o invece di || =
che è un logico o.
A partire da Perl 5.10 è preferibile utilizzare // =
. //
è l'operatore logico definito o non fallisce nel caso angolare in cui il valore corrente è definito ma falso.
Penso che il tuo problema stia utilizzando " | =
" (bit per bit o assegnazione) anziché " || =
" (assegnare se falso).
Nota che il tuo nuovo codice non è esattamente equivalente. La differenza è che " $ myhash {$ key} || = {}
" sostituirà i valori esistenti ma falsi con un riferimento hash, ma il nuovo no. In pratica, questo probabilmente non è pertinente.
Prova questo:
my %myhash;
$myhash{$key} ||= {};
Non puoi dichiarare un elemento hash in una clausola my
, per quanto ne so. Dichiarare prima l'hash, quindi aggiungere l'elemento.
Modifica: vedo che hai eliminato my
. Che ne dici di provare || =
invece di | =
? Il primo è idiomatico per "pigro" inizializzazione.