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

I have a hash of arrays that I'd like to use as stacks. Initially, the arrays are empty. Later in my code, I'm using one of these stacks at a time for some processing.

What I'd like to do is set a temporary reference equal to the result of the hash lookup and perform operations on that since this will eliminate unnecessary lookups and make my code a little less disgusting.

The problem I am having is that when I assign a reference to an undefined list, the modifications I make are not reflected. As soon as I add an element to the original list, everything works as expected. This would make sense if perl's hard references don't do anything special for undefined references.

Currently, I could do something really cheezy, like pushing and then popping once from each list at the start (which would create empty but "defined" arrays), but this doesn't seem particularly robust since this might change in the next perl revision.

So, is there a good way to create an array of size 0 that is also defined? Would using soft references fix this problem?

Please enlighten this humble novice, oh great perl monks.

  • Comment on creating defined references to arrays of size zero

Replies are listed 'Best First'.
Re: creating defined references to arrays of size zero
by Ovid (Cardinal) on Jul 14, 2005 at 05:08 UTC

    The problem I am having is that when I assign a reference to an undefined list, the modifications I make are not reflected.

    Maybe I'm a little slow (wouldn't be the first time), but I can't figure out what you mean. Could you show us a small code sample?

    my %stacks = ( stack1 => [], stack2 => [], );

    That should do what I think you want, but it seems straightforward enough that I assume I am not understanding your question.

    Cheers,
    Ovid

    New address of my CGI Course.

Re: creating defined references to arrays of size zero
by tlm (Prior) on Jul 14, 2005 at 05:31 UTC

    Like Ovid said:

    my %stacks = ( A => [], B => [], . . . Z => [], ); # microseconds later... my $current_stack = $stacks{ K }; # for example push @$current_stack, 'whatever'; # etc.;
    As long as you deal with references (like $current_stack) above, the changes you make will be reflected in the stacks stored in %stacks.

    You can initialize the stacks more succinctly with something like this:

    my %stacks; @stacks{ @names } = map [], @names;
    ...where @names holds the names of the stacks.

    the lowliest monk

      strange-- I was doing that. I tried to recreate the code on my home computer and it worked as you all said (and as I originally expected it to). I'm guessing either

      a) my work has a weird version of perl
      b) the larger code I'm working on has some strange options set

      Thanks for all your help.

        aha-- woke up and realized what I was doing-- definitely an ID 10-T error. Most of my keys were one letter, but one was actually a full word (I know the possible keys ahead of time), so I did something stupid like
        hash = { a=>[]; b=>[] c=>[] . . . } #some time later my $key = "alpha" my $array = $hash->{$key};

        At this point there isn't anything at $hash->{$key}, so $array isn't pointing to anything real. When I push onto $array, that memory will get allocated happily, and won't create anything in the hash (which is a very good thing). If instead, the first thing I do is to shove something into @{$hash->{$key}}, a new entry gets magically allocated, and then everything works as expected.

        Obviously I'm not one with the perl yet.

Re: creating defined references to arrays of size zero
by NetWallah (Canon) on Jul 14, 2005 at 05:19 UTC
    My interpretation of what you are looking for is :
    my %stacks; my $CurrentArrayRef = $Stacks{nonexistant} || []; # Line above CREATES a ref to an empty array if the stack was undefine +d. #It returns a ref to the contents if there were any. push @$CurrentArrayRef, "New Value"; ... more code ... # Now (re)store the contents into the stack $Stacks{nonexistant} = $CurrentArrayRef;

         "Income tax returns are the most imaginative fiction being written today." -- Herman Wouk

      my $CurrentArrayRef = $Stacks{nonexistant} || [];

      Better yet:

      my $CurrentArrayRef = $Stacks{ nonexistant } ||= [];
      This initializes $Stacks{ nonexistant } conditionally, and assigns its value to $CurrentArrayRef, thereby making this line:
      # Now (re)store the contents into the stack $Stacks{nonexistant} = $CurrentArrayRef;
      unnecessary.

      the lowliest monk

Re: creating defined references to arrays of size zero
by trammell (Priest) on Jul 14, 2005 at 05:10 UTC
    How about posting some code? I'll bet you anything that this is a PEBKAC.