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

Hi I am a new user in perl. My question is just how can change local array to global array in order to use in main program? for exapmle this is just part of my script:

my @species = split "//", $list; foreach my $species(@species) { my @tree = edit($species); print @tree; } sub edit { my ($species) = @_; if($species =~ /RANK *: subspecies/ && $species =~ /PARENT ID * : +(\d+)/) { my $pid = $1; # # print "$pid\n"; return `getz "[taxonomy:$pid]" -e`; } }

how can use @tree in main program? Thanks in advance tom

Replies are listed 'Best First'.
Re: local and global variable?
by davido (Cardinal) on Aug 22, 2011 at 08:41 UTC

    You declare it outside of the loop's enclosing block, and then instead of assigning to it within the block, you push onto it (so as not to clobber its contents on each iteration).

    my @species = split '//', $list; my @tree; foreach my $species ( @species ) { push @tree, edit( $species ); } print "$_\n" for @tree;

    ...for example (and assuming that's what you're after).

    It's wise to scope your variables as narrowly as conveniently possible. But if you need it at a broader scope, either declare it at that broader scope, or change your design so that it's not needed. Either solution may be fine depending on your goal.


    Dave

Re: local and global variable?
by Marshall (Canon) on Aug 22, 2011 at 09:11 UTC
    There are serious flaws with this code.

    For example, my @species = split "//", $list;. The @species array will contain each letter of $list (a split on the null string is every letter of the original string).

    update: Opps... @species = split(//,$list) is not @species = split("//",$list). A cross-eyed booboo on my part. Sorry.

    @tree will contain the lines returned from the "backtick" command in the subroutine. The foreach loop is the main program as presented.

    my @tree_array; # my @species = split "//", $list; # would: # foreach my species ('a','b','c') {} work? I think not? foreach my $species(@species) { my @tree = edit($species); push @tree_array, [@tree] if @tree; print @tree if @tree; } ## do you want to use @tree here? ## if so, then ...you need to use the array ## of the @tree results... foreach $tree_ref (@tree_array) { print "@$tree_ref\n"; } sub edit { my ($species) = shift; #slightly faster when just one arg my ($pid) = ($species =~ /RANK.*?subspecies.*?PARENT ID.*?(\d+)/); ### or ### ## look for "PARENT ID", then anything until there are ## one or more digits my ($pid) = ($species =~ /PARENT ID.*?(\d+)/); if (defined $pid) { return `getz "[taxonomy:$pid]" -e`; } return undef; }
    Feel free to modify the above code, show a runnable example of your problem.
      ... my @species = split "//", $list;. The @species array will contain each letter of $list (a split on the null string ...

      Splitting on  "//" does not split on the null string, but rather on the literal sequence of two forward-slash characters.

      >perl -wMstrict -le "my $s = 'foo//bar//baz'; my @species = split qq{//}, $s; printf qq{'$_' } for @species; " 'foo' 'bar' 'baz'
        my booboo corrected above. Thanks for pointing this mistake out.

        It was an accident waiting to happen. This is one reason I always make it clear in my code that the first argument of split is a regular expression pattern, not a string.

        my @species = split m{//}, $list;
Re: local and global variable?
by ricDeez (Scribe) on Aug 22, 2011 at 18:02 UTC

    Being new to Perl, one of the things that you want to avoid is getting mixed up with your scalars and arrays, which is easy to do when you use similar names for your scalars and arrays (i.e. $species and @species). Whilst, it is true that this word uses the same form for its singular and plural forms, a more apt name may be $sp for you scalar variable (i.e. singular abbreviation). It is not considered good form to name variables as you have done here.

    You may also want to read up on variable scoping rules in Perl to understand why my @tree is not accessible outside the for loop.