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?

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top