in reply to Autovivification not working?

Thanks, all who replied. However, I forgot something while trying to narrow it down. One of the hashes is a tie()d array, and that's what goes wrong for some reason.

So much for trying to find out where it goes wrong. Here's the real script:
2;0 juerd@ouranos:~$ rm karmatest 2;0 juerd@ouranos:~$ perl test.pl Use of uninitialized value in addition (+) at test.pl line 31. 2;0 juerd@ouranos:~$ cat test.pl #!/usr/bin/perl -w package Karma; use GDBM_File; use strict; sub new($$){ my ($prot, $file) = @_; my $self = { hash => {} }; $self->{object} = tie %{ $self->{hash} }, 'GDBM_File', $file, GDBM +_WRCREAT, 0640; bless $self, $prot; return $self; } sub resolve($$){ my ($self, $subject) = @_; $subject = lc $subject; my $recur = 0; if (defined $self->{hash}{$subject}){ while ($self->{hash}{$subject} =~ /^S:(.*)/){ $subject = 'ERECURSIE', last if ++$recur > 10; $subject = lc $1; } } # The next line was put in to work around the warning. # $self->{hash}{$subject} = 0 unless defined $self->{hash}{$subject} +; return \ $self->{hash}{$subject}; } sub incr($$;$){ my ($self, $subject, $d) = @_; #line 31 return ${ $self->resolve($subject) } += defined($d) ? $d : 1; } sub decr($$;$){ my ($self, $subject, $d) = @_; return ${ $self->resolve($subject) } -= defined($d) ? $d : 1; } sub get($$){ my ($self, $subject) = @_; my $foo = ${ $self->resolve($subject) }; print "BLAAT: $foo\n"; return $foo; } sub set($$$){ my ($self, $subject, $new) = @_; return ${ $self->resolve($subject) } = $new; } sub reorganize($){ $_[0]->{object}->reorganize(); } 1; package main; my $karma = Karma->new('karmatest'); $karma->incr('foo'); # foo must not exist

I'm sorry to have disappointed you by leaving out a very important part.

2;0 juerd@ouranos:~$ perl -e'undef christmas' Segmentation fault 2;139 juerd@ouranos:~$

Replies are listed 'Best First'.
Re: Re: Autovivification not working?
by jepri (Parson) on Dec 20, 2001 at 19:27 UTC
    It's still the same deal. Your hash element has been autovivified and set to undef. This is what the warning is - you are using the undef as a number. If your hash had not been autovivified, your would have received a "Expected reference...." error when trying to access the value.

    The way you have avoided the warning is the correct way to do it, although you can be slightly more compact with:

    $self->{hash}{$subject} ||= 0;

    In summary, you are trying to fix the wrong problem. Perl isn't being tricky this time. All it's doing is warning you that it is turning an 'undef' into a '0' for the addition. This is what you want.

    ____________________
    Jeremy
    I didn't believe in evil until I dated it.

      --, ++, -=, += and friends shouldn't complain about undefined variables, according to documentation.
      That's why perl -wMstrict -e'my $a = undef; $a++;' does not complain, nor does $hash{foo}++.

      But when the hash in quesion is tied AND a hashref AND in another hash, perl suddenly _does_ complain.
      I tried narrowing it down to the essential bits again, succesfully this time.
      As you can see in the paste below, everything is fine with the second one, which would be exactly the same if it were tie()d.

      2;0 juerd@ouranos:~$ cat test.pl #!/usr/bin/perl -w use GDBM_File; use strict; unlink 'karmatest'; my $hashref = { hash => {} }; $hashref->{object} = tie %{ $hashref->{hash} }, 'GDBM_File', 'karmates +t', GDBM_WRCREAT, 0640; sub resolve { return \ $hashref->{hash}{$_[0]}; } # Warning! ${ resolve('this one does not exist') } += 2; # now, the same, but without tie: my $second = { hash => {} }; sub resolve_again { return \ $second->{hash}{$_[0]}; } # No warning! ${ resolve('this one does not exist') } += 2; 2;0 juerd@ouranos:~$ perl test.pl Use of uninitialized value in addition (+) at test.pl line 13.


      I think my inability to express what I mean in English is the biggest problem here :(

      2;0 juerd@ouranos:~$ perl -e'undef christmas' Segmentation fault 2;139 juerd@ouranos:~$

        --, ++, -=, += and friends shouldn't complain about undefined variables, according to documentation.

        But you aren't using a variable, you are using a tied hash. I don't have the right modules installed, so try using B::DeParse to see what perl is doing to your program. <BS mode on> I haven't checked this but I bet perl is turning your 'variable' into a function call to something like (I last read the tie page many moons ago) $resolve->STORE('this one does not exist', $resolve->FETCH('this one does not exist') + 2)  <BS mode off>

        Let me know what it B::DeParse does to your code - I'm interested.

        Read more about tied hashes here.

        ____________________
        Jeremy
        I didn't believe in evil until I dated it.