http://qs321.pair.com?node_id=611184

Bro. Doug has asked for the wisdom of the Perl Monks concerning the following question:

Esteemed Monks,

I understand that undef() and hashes are not meant for each other. That said, I was wondering if anyone could specifically explain the wierdness occurring when you run the following piece of code.
#! /usr/bin/perl use strict ; use warnings ; local $\ = "\n" ; # some formatting my %h ; print ( defined %h ? "Defined!" : "Undefined!" ); undef( %h ) ; print ( defined %h ? "Defined!" : "Undefined!" ); %h = undef ; print ( defined %h ? "Defined!" : "Undefined!" ); undef( %h ) ; print ( defined %h ? "Defined!" : "Undefined!" ); #OUTPUT #Undefined! #Undefined! #Defined! #Undefined!

It seems to me that the hash is undefined until you try to assign something to it, and it doesn't matter what that something is. Also, I'm confused as to why, in this case, using undef as a function actually performs the undefine on the hash.

Peace monks,

Update:
I've followed advice and added use warnings and use strict (this started as a perl -e that was being passed around my office). We've also used Data::Dumper on it, just for play.
Bro. Doug :wq

Replies are listed 'Best First'.
Re: hash assignment wierdness
by DigitalKitty (Parson) on Apr 20, 2007 at 16:00 UTC
    Hi Bro. Doug.

    As mentioned in the chatterbox by andye++, the Data::Dumper module, while not perfect, is a useful tool.
    #!/usr/bin/perl use warnings; use strict; use Data::Dumper; my %hash = undef; print Dumper \%hash; #Output $VAR1 = { '' => undef };


    Update: bart++ for suggesting a reference to %hash.

    Hope this helps,
    ~Katie
      The output of Data::Dumper is misleading here, as it looks like undef was assigned to the value, not the key. But it's the key that gets the scalar:
      qwurx [shmem] ~ > perl -le '%h = "one"; print "$_ => $h{$_}" for keys +%h' one =>

      --shmem

      _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                    /\_¯/(q    /
      ----------------------------  \__(m.====·.(_("always off the crowd"))."·
      ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: hash assignment wierdness
by logie17 (Friar) on Apr 20, 2007 at 15:56 UTC
    Well what's interesting is if you use strict/warnings the following error message appears on line 13:
    Odd number of elements in hash assignment at ./test1.pl line 13. Use of uninitialized value in list assignment at ./test1.pl line 13.

    Normally you don't assign a %hash one value but a key/value pair.
    s;;5776?12321=10609$d=9409:12100$xx;;s;(\d*);push @_,$1;eg;map{print chr(sqrt($_))."\n"} @_;
Re: hash assignment wierdness
by Errto (Vicar) on Apr 20, 2007 at 17:59 UTC
    The way to assign no elements to a hash is
    %h = ();
    After this statement defined %h returns false. Whereas
    %h = undef;
    is assigning a single key to the hash (whose value happens to be undef, and thus coerced into the empty string '') with no corresponding value, hence the warning. But after this assignment the hash is no longer empty, so defined %h returns true.
Re: hash assignment wierdness
by Ploux (Acolyte) on Apr 20, 2007 at 16:00 UTC
    I believe the following pairs are equivalent.
    %hash = undef; %hash = (undef => ''); %hash = 'one'; %hash = (one => ''); @array = 'one'; @array = ('one');
Re: hash assignment wierdness
by Obidan (Initiate) on Apr 20, 2007 at 18:06 UTC
    The issue is that undef nulls out it's arguments and then returns a scalar value. when you assign something undef, it is not really the *absence* of a value, it is a reserved scalar that perl uses to indicate absence of genuine data.

    Digging into hash_file.c would most likely reveal that the hash operators make no special case for undef, and treats it as it would any other scalar value in assignmets. So as far as perl is concerned, when you assign undef to a hash, you're asking it for a hash containing the undef value.

    As far as I am aware, the only way to null out a hash is to use it as an argument to undef, as in your example code.

    Obidan :wq