We needed to have hashes where values could be found in the hash, even 
if a key was used that had a different case than the original key used 
to put the value into the hash. So, I investigated tied hashes in Perl, 
and soon developed a library to do just that, which seemed to work fine, 
until recently, when I found that sometimes my hash objects acted as 
though they were empty, when clearly they were not. In fact, I ran into 
this strange situation:

# --- $hTied exists and is a tied hash

foreach my $key (keys(%$hTied)) {
    print("$key = $hTied->{$key}\n");
    }

# --- the above prints nothing, as if the hash %$hTied has no keys, but

my $h2 = $hTied->{prod1};
foreach my $key (keys(%$hTied)) {
    print("$key = $hTied->{$key}\n");
    }

# --- the above prints out several keys and values
# --- i.e. it looks like $hTied is empty, but $hTied->{prod1}exists and 
contains data

I eventually tracked the problem down to the fact that my tied hash 
contained an entry with an undef key. Normal hashes in Perl not only 
allow that, but work perfectly. The entry with the undef key can be 
retrieved like any other key:

my $h = {
    a => 1,
    undef , 2,
    c => 3,
    };

foreach my $key (keys(%$h)) {
    print("'$key' => '$h->{$key}'\n");
    }

prints out:

'' => '2'
'c' => '3'
'a' => '1'

(but note that I couldn't say  undef => 2 because the magic of => would 
cause it to treat undef as the string 'undef'. Also, my printing routine 
doesn't distinguish between keys that are undef and keys that are the 
empty string, but I could remedy that by making the foreach loop a bit 
more complex by checking to see if $key is defined or not)

So, understanding the problem, I figured that I'd go into my library and 
simply fix the problem. So, I looked at my FIRSTKEY function. What it is 
supposed to do is to retrieve the first key, and the first value and 
return the first key in scalar context, or the pair first key and first 
value if in list context. If there are no keys in the hash, it's 
supposed to return undef in scalar context, but the empty list if in 
array context. Well, we've got a serious logical problem if the first 
key in the hash is undef - since returning undef in scalar context is 
how we're supposed to indicate that there are no keys.

Also, I should mention that I found 2 other Perl libraries that are 
supposed to do the same thing, i.e. have case insensitive retrieval of 
values from a hash while retaining the original case of the keys. These 
are Tie::CPHash and Hash::Case::Preserve. I found that both of these 
libraries also have the same problem with undef keys.

The solution I'm going to use in my library is to convert undef keys to 
the empty string - probably on insert, but it would also work to return 
the empty string for undef keys found in the FIRSTKEY and NEXTKEY 
functions.

It's a bit annoying that with tied hashes, it seems to be impossible to 
emulate the behavior of real Perl hashes with respect to undef keys. If 
anyone knows of a way around this problem that would allow tied hashes 
to work just like true Perl hashes, except that lookups would be 
case-insensitive. Also, if anyone knows of a library implemented in C 
code, which would be much faster than any of the libraries mentioned, 
that did this, I'd appreciate knowing about it. A google search didn't 
turn up any such library.
_______________________________________________
Perl-Win32-Users mailing list
Perl-Win32-Users@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

Reply via email to