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

I'm converting a mod-perl2 module from having lots of global variables to having just read-only globals, with an eye toward maybe running it under a threaded Apache MPM in the future. The 'handler' calls a subroutine 'checkForm', which fills an array with various data that it wants to pass to a subroutine 'showPage' that the handler calls later. This array is declared in the handler, and is passed by reference to checkForm and showPage:
sub handler { my @items2show; ... checkForm (..., \@items2show); ... showPage (..., \@items2show); ... }
Items in @items2show are identified by a set of global subscript constants near the start of the script, one of which might be
use constant ARRAYX => 3;
One of the things that checkForm wants to pass to showPage in @items2show is an array that's anonymous other than being passed by reference as items2show[ARRAYX]. Near the start of checkForm the overall items2show array is initialized. Later in checkForm, value(s) want to be pushed onto the ARRAYX array.
sub checkForm { my (..., $items2show_ref) = @_; @$items2show_ref = (); $$items2show_ref[ARRAYX] = []; # should this be () ?? ... push @??ARRAYX??, $value; ... }
I've tried various syntaxes in the push statement above, and cannot get Perl to accept any of them. Also I'm not clear on whether the initializer for the ARRAYX array wants to be [] or (), although this can be worked thru if I can get the push syntax right...

Summarizing:
Q1: push WHAT?
Q2: [ ] or () ?

Of course if there's a better way to do the whole thing, I'm all ears...
Thanks for being there,
cmac

Replies are listed 'Best First'.
Re: getting in trouble avoiding global variables
by webfiend (Vicar) on Dec 09, 2008 at 00:25 UTC

    Quick and dirty: Use [] to initialize an arrayref. Also, arrow notation makes most things clearer to me.

    sub checkForm { my (..., $items2show_ref) = @_; $items2show_ref = []; $items2show_ref->[ARRAYX] = []; # ... push @{ $items2show_ref->[ARRAYX] }, $value; }

    Good luck cleaning up the old code, by the way. That sort of pastime caused a good 50% of my gray and missing hairs.

Re: getting in trouble avoiding global variables
by GrandFather (Saint) on Dec 09, 2008 at 00:46 UTC

    The immediate problem is syntax. $items2show_ref is a reference so you need to dereference it. It's referencing an array so you need $items2show_ref->[ARRAYX] to get at an element of the array. Often the array element will be a reference too so you need to dereference that. If the element references an array you can @{$items2show_ref->[ARRAYX]} to work with the referenced array or $items2show_ref->[ARRAYX][$element] to get at an element.

    I'd use a hash instead of an array or, even better, use light weight OO. Using a hash there is a small change from $items2show[kArrayX] to $items2show{ArrayX} with the advantage that you don't need to generate the constant (and the disadvantage that you get run time rather than compile time errors for typos).

    Using light weight OO you could use the same access techniques as you do for either a hash or an array, or you could provide methods for wrapping up tricky stuff:

    my $obj = bless {}; $obj->checkForm (...); $obj->showPage (...); sub checkForm { my ($self, @params) = @_; ... $self->addArrayXValue ($value); ... } sub showPage { my ($self, @params) = @_; my $value = $self->getArrayXValue (-1); ... } sub addArrayXValue { my ($self, $value) = @_; push @{$self->{arrayX}}, $value; } sub getArrayXValue { my ($self, $index) = @_; return $self->{arrayX}[$index]; }

    Perl's payment curve coincides with its learning curve.
      Thanks to all 3 of you for the replies. The fact that all of you agreed on the proper syntax for the push made your answers particularly convincing. Before I checked back, I had gotten the compiler to accept @{$$items2show_ref [ARRAYX]} which may be the same semantics as @{$items2show_ref->[ARRAYX]}, but I changed to the latter form on the grounds that it is less ugly, and may be more correct as well. Thanks, cmac
Re: getting in trouble avoiding global variables
by BrowserUk (Patriarch) on Dec 09, 2008 at 00:23 UTC

    In words: $items2show_ref is a reference (->), to an array ([...]), that has an element at offset ARRAYX that is a reference to an array (@{ ... }), onto which you wish to push $value:

    push @{ $items2show_ref->[ARRAYX] }, $value;

    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.
Re: getting in trouble avoiding global variables
by ww (Archbishop) on Dec 09, 2008 at 01:45 UTC