Sean Kelleher
Sean Kelleher

Reputation: 2102

Declaring global variables in a subroutine in perl

I was wondering if it's possible to declare a global variable within a subroutine in Perl so that I can use that variable in a hooked void function, but limiting the damaging effects of the global by having it declared in a subroutine.

So the subroutine uses XML::Parser to collect the IDs of a bunch of elements, in a manner similar to:

sub getRecipeIDs {
    my $recipe = shift;
    my @elements = ();

    my $parser = new XML::Parser(Style => 'Tree',
        Handlers => {
            Start => sub {
                my ($expat, $element, %attrs) = @_;
                if ($element eq 'recipe') {
                    push @elements, $attrs{id};
                }
        }});

    $parser->parse($recipe);

    return @elements;
}

I'm also using strict in my script.

So I want to declare @elements in such a way that it is local to getRecipeIDs but is visible to the anonymous subroutine.

Thanks for your time, any help is greatly appreciated.

Upvotes: 2

Views: 916

Answers (3)

Borodin
Borodin

Reputation: 126772

Your code should work fine as it stands

Despite the depth of the anonymous subroutine, its scope includes the lexical array @elements and it can access it freely

Furthermore the subroutine counts as a reference to the array, so it will not be garbage collected when it goes out of scope at the end of the call to getRecipeIDs

Upvotes: 3

user507077
user507077

Reputation:

It should already work the way in which you've written your example. What you're doing with "my $func = sub { ... }" is you create a closure which has access to the enclosing scope's variables -- in this case @elements.

Upvotes: 6

Stefan Majewsky
Stefan Majewsky

Reputation: 5555

my is fine. Lexical variables are visible in nested scopes, such as anonymous subroutines.

Your code should therefore work as-is.

Upvotes: 3

Related Questions