metaperl has asked for the wisdom of the Perl Monks concerning the following question:

I think some behavior in Perl hash usage has changed. It used to be that $hash{test_elem} would set that hash key to a value of '' (empty string).

But in the following program:

#!/usr/local/bin/perl use strict; use warnings; use Data::Dumper; sub find_numbers { my ($amount, $map)=@_; my $start = 11; my @found; while ($amount--) { while ($map->{$start}) { ++$start; } push @found, $start++; } @found; } my %map = ( '11' => 1, '12' => 1, '15' => 1,); my @free_numbers = find_numbers(4, \%map); die Dumper(\@free_numbers, \%map);
we see that %map does not end up having all the various values that were tested via the expression  while ($map->{$start})

Why is that?



The mantra of every experienced web application developer is the same: thou shalt separate business logic from display. Ironically, almost all template engines allow violation of this separation principle, which is the very impetus for HTML template engine development.

-- Terence Parr, "Enforcing Strict Model View Separation in Template Engines"

  • Comment on When testing for certain hash positions as non-zero, why werent the test positions set to empty string?
  • Select or Download Code

Replies are listed 'Best First'.
Re: When testing for certain hash positions as non-zero, why werent the test positions set to empty string?
by ikegami (Patriarch) on Aug 23, 2010 at 15:31 UTC

    I think some behavior in Perl hash usage has changed. It used to be that $hash{test_elem} would set that hash key to a value of '' (empty string).

    How would you know it no longer does that? Your code doesn't demonstrate this. (I see the Dumper now)

    That said, it's true that Perl doesn't do that, and I doubt it ever did. Here's how Perl behaves:

    • When $hash{test_elem} is used as an rvalue, it doesn't modify the hash.

      $ perl -wle'my $x = $hash{test_elem}; print keys %hash'
    • When $hash{test_elem} is used as an lvalue, the element must exists, so it's created. Like other variables, it starts up undefined.

      $ perl -wle'my $r = \$hash{test_elem}; print keys %hash; print defined +($hash{test_elem})?1:0;' test_elem 0 $ perl -wle'1 for $hash{test_elem}; print keys %hash; print defined($h +ash{test_elem})?1:0;' test_elem 0
      There's special code in place to avoid creating the element unless necessary when passed to a sub.
      $ perl -wle'sub {}->($hash{test_elem}); print keys %hash' $ perl -wle'sub { $_[0]=1; }->($hash{test_elem}); print keys %hash' test_elem
    • If you dereference an undef scalar (including a hash value), autovivification will create a variable of the appropriate type and store a reference to it in the scalar.

      $ perl -wle'my $r; $r->{x}; print $r;' Useless use of hash element in void context at -e line 1. HASH(0x816c158)

    In no case does Perl assign an empty string to a scalar. Undef does resemble the empty string, but not in Dumper's output.

Re: When testing for certain hash positions as non-zero, why werent the test positions set to empty string?
by moritz (Cardinal) on Aug 23, 2010 at 14:54 UTC
    I think some behavior in Perl hash usage has changed. It used to be that $hash{test_elem} would set that hash key to a value of '' (empty string).

    That's new to me. Care to demonstrate that with an older perl, or provide a pointer to some documentation or so?

    What does happen is autovivification if you access a second-level hash element when the first level does not exist, ie $hash{a}{b} initializes $hash{a} to an empty hash reference.

    Perl 6 - links to (nearly) everything that is Perl 6.
Re: When testing for certain hash positions as non-zero, why werent the test positions set to empty string?
by BrowserUk (Patriarch) on Aug 23, 2010 at 14:55 UTC

    You seem to be saying that at some point in history, perl autovivified uninitialised hash elements to the null string. To my knowledge, that has never been the case. They have always been set to undef.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Yes. And using an undefined value as if it were a string makes it act like an empty string. Perhaps the OP hadn't enabled warnings, and saw this behaviour, leading to the confusion.

      But that's a lot of speculation.