2010-10-18 4 views
5

Je le script ci-dessous (idéalisée d'un bug) en Perl:Pourquoi mon hash n'est-il pas indéfini?

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

Pour une raison quelconque la sortie du programme est toujours « défini ». Le réglage du hash pour qu'il soit "indéfini" le rend en quelque sorte défini. Est-ce défini comme étant "indéfini"?

EDIT:

Ceci est un cas idéalisé, dans une tentative de reproduire le problème. Ce que je suis en fait de faire est plus comme:

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

Lorsque la sortie de my_sub_function peut être indéfinies,() ou un hachage peuplé, et je veux seulement imprimer « défini » dans le dernier de ces cas.

EDIT 2:

Soit dit en passant, j'ai trouvé que

if (scalar(keys %metadata) 

se conduit correctement pour(), mais pas encore pour le FNUD.

+3

Est-ce que '' my_sub_function' faire retour undef' i Indiquer un échec ou aucune donnée? Si c'est le cas, il devrait probablement faire un «retour» nu à la place. Cela serait interprété comme 'undef' dans un contexte scalaire et'() '(la liste vide) dans un contexte de liste. –

Répondre

8

Si votre fonction retourne undef et que le FNUD est placé dans le hachage, les changements auto-FNUD qui en chaîne de '' être et vous vous retrouvez avec: %metadata = ('' => undef).

Si votre fonction a besoin pour revenir soit undef, () ou un hachage approprié et vous avez besoin de tester les trois cas séparément, je vous suggère:

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"; 
} 

Vous pouvez le tester avec les my_sub_functions suivants :

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 

hacking heureux

+1

Merveilleux; Merci beaucoup! Perl me surprend toujours avec la facilité avec laquelle il fait des choses difficiles, et comme certaines choses qui devraient être simples deviennent difficiles :) –

8

Essayez

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

Je pense qu'il était juste en utilisant un « undef » en tant que données pour alimenter le hachage.

« utilisation des avertissements » auraient dit:

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. 

FNUD,() ou un hachage peuplé

Si vous voulez vraiment faire la distinction entre un hachage vide et aucun hachage, mieux utiliser une référence de hachage (également plus légère pour passer à travers le sous-programme, pas de copie par passage et tout).

+0

ah, intéressant! Je n'ai pas vu cette erreur dans mes journaux, et le code dont il provient utilise des avertissements stricts et d'utilisation. J'ai aussi essayé sans défini (% hash), avec les mêmes résultats cependant. –

+0

Malheureusement je ne suis pas responsable de ce qui revient directement de la sous-fonction, donc je dois travailler avec ce que l'on me donne :) –

+0

"L'utilisation de defined sur les agrégats (hachages et tableaux) est obsolète. si la mémoire pour cet agrégat a déjà été allouée.Ce comportement peut disparaître dans les futures versions de Perl.Vous devriez plutôt utiliser un test simple pour la taille ". Donc, votre approche actuelle pourrait ne pas fonctionner trop bien. Mieux vaut parler aux gens qui ont fait ce sous-programme. – Thilo

1

essayer cette

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

Et si vous regardez la documentation sur perldoc -f defined, il dit cette façon de vérifier est dépréciée.

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

si vous voyez la documentation de defined, vous constaterez que,

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

essayer simple, if (%a_hash) { print "has hash members\n" }

Note: undef est la valeur d'une variable qui n'a jamais été initialisé (ou qui a été réinitialisé en utilisant la fonction undef). The defined function returns true if the value of the expression is not undef.

Questions connexes