Domanda

Ho un codice Perl simile al seguente:

# -- start --

my $res;

# run query to fetch IPv6 resources
while( my $row = $org_ip6_res->fetchrow_arrayref )
{
    if( $row->[4] =~ /PA/ ) {
        $res->{ipv6}{pa}{$row->[2]}++;
    } elsif( $row->[4] eq 'PI' ) {
        $res->{ipv6}{pi}{$row->[2]}++;
    }
}

# -- stop --

In nessun momento $ res è mai stato impostato prima di scorrere i risultati della query, ma il codice funziona bene.

Quando metto le istruzioni di stampa prima di ogni valore ottengo spazi vuoti in entrambi i casi, ma se le istruzioni di stampa vengono dopo l'applicazione dell'incremento ottengo un valore di > = 1 a seconda di quante risorse IPv6 l'organizzazione ha.

La mia domanda è, devo prendere questo per significare che una chiave hash non inizializzata in Perl ha automaticamente un valore pari a zero?

Mi dispiace se si presenta come una domanda da principiante, ma non ho familiarità con un tale costrutto ovvero $ hashref- > {foo} - > {bar} ++ dove un valore deve ancora essere assegnato esplicitamente a $ hashref- > {foo} - > {bar} . Grazie in anticipo!

È stato utile?

Soluzione

Il valore non è automaticamente zero. Il valore inizialmente non è definito. Tuttavia, se lo tratti come un numero (ad esempio, applica ++ ), Perl lo tratta come zero. Se lo tratti come una stringa (ad esempio, applica . ), allora Perl lo tratta come una stringa vuota.

Da perldoc perlsyn , sotto "Dichiarazioni":

  

Le uniche cose che devi dichiarare   Perl sono formati di report e   subroutine (e talvolta nemmeno pari   subroutine). Una variabile contiene il   valore indefinito ("undef") fino a quando non lo è   stato assegnato un valore definito, che   è qualcosa di diverso da "undef". quando   usato come un numero, "undef" è trattato   come 0; se usato come stringa, lo è   trattata come una stringa vuota, "quotata"; e   se usato come riferimento che non lo è   essendo assegnato a, viene trattato come un   di errore.

Altri suggerimenti

Per approfondire il post di Telemaco, i valori non inizializzati saranno indefiniti. Le parti profonde della struttura sono autovivificati . Questa è una funzione utile in cui le strutture dati vengono create automaticamente per te. L'autovivificazione è ottima quando la vuoi, ma può essere una seccatura quando vuoi prevenirla. Esistono molti tutorial, articoli e post in rete sulla comprensione dell'autovivificazione.

Così dato un $ ref e $ ref- > {ipv6} {pa} {'foo'} ++ , $ ref verrà assegnato un valore di:

$ref = { 
     ipv6 => { 
          pa => { 
              foo => undef
          }
     }
};

Quindi undef verrà incrementato, poiché undef numera a 0, otteniamo 0 ++ che è 1. Per un risultato finale di: ref- > {ipv6} {pa} {'foo'} == 1 .

Se hai gli avvisi abilitati, (usi usi gli avvertimenti; , vero?) otterrai un valore " non inizializzato " avviso quando si opera su questi valori non definiti. Se è il comportamento desiderato aumentare il valore unitario, è possibile disattivare il gruppo desiderato di avvisi su una parte limitata del codice:

use strict;
use warnings;
my $res;

// run query to fetch IPv6 resources
while( my $row = $org_ip6_res->fetchrow_arrayref )
{   no warnings 'uninitialized';
    if( $row->[4] =~ /PA/ ) {
        $res->{ipv6}{pa}{$row->[2]}++;
    } elsif( $row->[4] eq 'PI' ) {
        $res->{ipv6}{pi}{$row->[2]}++;
    }
}

Puoi trovare la gerarchia degli avvisi in perllexwarn .

È sostanzialmente indefinito, ma trattato come se fosse zero quando lo incrementi.

Il termine nel linguaggio Perl è "autovivificato".

Quello che probabilmente vorresti fare è usare la esiste una parola chiave :

$res->{ipv6}{pa}{$row->[2]}++ if exists($res->{ipv6}{pa}{$row->[2]});

Non esiste una chiave hash non inizializzata . La cosa che non può essere inizializzata è il valore per una chiave particolare. Un valore hash è solo un valore scalare; non è diverso da una variabile come $ foo .

Esistono un paio di diverse funzionalità Perl che interagiscono nel tuo esempio.

Inizialmente $ res non è definito (ovvero ha il valore undef ). Quando usi un valore non inizializzato come riferimento di hash (come in $ res- > {ipv6} ... ) Perl "quota automaticamente" come uno. Cioè, Perl crea un hash anonimo e sostituisce il valore di undef con un riferimento al nuovo hash. Questo processo si ripete (in silenzio) ogni volta che si utilizza il valore risultante come riferimento.

Alla fine, ti autovivizzi verso $ res- > {ipv6} {pa} {$ row- > [2]} , che non è definito. Ricorda che questo è solo un valore scalare come $ foo . Il comportamento è lo stesso di

my $foo;
$foo++;

Perl fa cose speciali quando usi valori non definiti. Se li usi come numero, Perl li converte in 0. Se li usi come stringa, Perl li converte in '' (la stringa vuota). Nella maggior parte dei casi otterrai un " Uso di valore non inizializzato ... " avviso se hai gli avvisi abilitati (che dovresti). L'operatore auto-increment ( + + ) è un caso speciale, però. Per comodità, converte silenziosamente il valore da undef a 0 prima di incrementarlo.

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