2010-10-18 17 views
5

Ho il seguente (idealizzato da un bug) breve script in Perl:Perché il mio hash non è undef?

my %metadata = undef; 
if (defined %metadata) 
{ 
    print "defined"; 
} 

Per qualche motivo l'output del programma è sempre "definito". Quindi impostare l'hash come "non definito" lo rende in qualche modo definito. È definito come "non definito"?

EDIT:

Questo è un caso idealizzato, nel tentativo di replicare il problema. Quello che sto facendo in realtà è più simile a:

my %metadata = my_sub_function(); 
if (defined %metadata) 
{ 
    print "defined"; 
} 

in cui l'uscita di my_sub_function può essere undef,() o un hash popolata, ed io per stampare solo "definito" l'ultimo di questi casi.

EDIT 2:

Per inciso ho trovato che

if (scalar(keys %metadata) 

si comporta correttamente per(), ma ancora non per undef.

+3

fa 'my_sub_function' fare un' ritorno undef' per i ndicate fallimento o nessun dato? Se è così, dovrebbe probabilmente fare un semplice 'ritorno 'invece. Questo sarebbe interpretato come 'undef' nel contesto scalare e'() '(la lista vuota) nel contesto dell'elenco. –

risposta

8

Se la funzione restituisce undef e che undef è posto nei cambiamenti hash, auto-a stringa che undef essere '' e si finisce con: %metadata = ('' => undef).

Se la vostra funzione ha bisogno per tornare sia undef, () o un hash corretta ed è necessario testare tutti e tre i casi a parte, io suggerirei:

my %metadata = my_sub_function(); 
if (!scalar keys %metadata) { 
    print "An empty list() was returned\n" 
} elsif (
    scalar keys %metadata == 1 and 
    exists $metadata{''} and 
    !defined $metadata{''} 
) { 
    print "undef or '' was returned\n"; 
} else { 
    print "A hash was hopefully returned\n"; 
} 

Si potrebbe provare con le seguenti my_sub_functions :

sub my_sub_function { return()     } # 1st case 
sub my_sub_function { return undef    } # 2nd case 
sub my_sub_function { return (a => 1, b => 2) } # 3rd case 
sub my_sub_function { return qw/not a hash/  } # unhandled case 

felice l'hacking

+1

Meraviglioso; grazie mille! Perl mi sorprende sempre con la facilità con cui rende alcune cose difficili, e con quale intensità alcune cose che dovrebbero essere semplici diventano :) –

8

Prova

my %metadata; 
undef %metadata; 
if (defined %metadata) 
{ 
    print "defined"; 
} 

Credo che sia stato solo usando un "undef" come dati per popolare l'hash.

"use warnings" avrebbero detto:

defined(%hash) is deprecated at t.pl line 6. 
    (Maybe you should just omit the defined()?) 
Odd number of elements in hash assignment at t.pl line 4. 
Use of uninitialized value in list assignment at t.pl line 4. 

undef,() o un hash popolata

Se davvero si vuole distinguere tra un hash vuoto e nessun hash, meglio usa un riferimento all'hash (anche più leggero per passare dalla subroutine, nessuna copia passata e tutto).

+0

ah, interessante! Non ho visto questo errore nei miei registri e il codice da cui proviene usa avvisi severi e uso. Ho anche provato senza definito (% hash), con gli stessi risultati però. –

+0

sfortunatamente non sono responsabile di ciò che ritorna direttamente dalla sotto funzione, quindi devo lavorare con quello che mi viene dato :) –

+0

"L'uso di definito su aggregati (hash e matrici) è deprecato. se la memoria di quell'aggregato è mai stata allocata, questo comportamento potrebbe scomparire nelle future versioni di Perl. Dovresti invece usare un semplice test per la dimensione ". Quindi, il tuo approccio attuale potrebbe non funzionare troppo bene. Meglio parlare con le persone che hanno fatto quella subroutine. – Thilo

1

provare questo

%metadata=("1"=>"one"); 
undef %metadata; 
if (%metadata) 
{ 
    print "defined"; 
} 

E se si guarda la documentazione sul perldoc -f defined, si dice che questo modo di controllo è deprecato.

Use of "defined" on aggregates (hashes and arrays) is deprecated. 
2

se si vede la documentazione di defined, troverete che,

When defined used on a hash element, 
it tells you whether the value is defined, 
not whether the key exists in the hash. 

provare semplice, if (%a_hash) { print "has hash members\n" }

Nota: undef è il valore di una variabile che non è mai stato inizializzato (o che è stato ripristinato utilizzando la funzione undef). The defined function returns true if the value of the expression is not undef.

Problemi correlati