in reply to Sub in a Sub & Recursion

hakkr,

The first example works because the lexical @files is visible to the FileName subroutine (since both are defined within the Get_Saves subroutine block). This works because you have the scope correct.

The second example will not work for several reasons: 1, File::Find::find does not return anything; 2, \&FileName(\@files) is not a reference to a subroutine (only \&FileName is); and three, the @files in Get_Saves is a different beastie than the @files in FileName (the first is a lexical and the second is a global.

To use File::Find with the two seperate functions, you would need to use either global @files or a lexical @files defined outside of Get_Saves and FileName:

#!/usr/bin/perl use strict; use File::Find; my @files; # could leave this out and just let FileName # auto-vificate global @files Get_Saves(); sub Get_Saves { find( \&FileName, "/usr/local/apache/htdocs/service/" ); } sub FileName { unless( ($_ eq ".") or ($_ eq "temp.svd")) push( @files, $_ ); # This @files is either the lexical declared above # or an auto-vifified global if nothing was declared # above. }

update I really like goldclaw's Re: Sub in a Sub & Recursion but you would need to remove the "@files=" from the find since File::Find::find always returns nothing. Just do this:

#where to add stuff. find(FileName(\@files),"/usr/local/apache/htdocs/service/"); return \@files, $#files+1;

-derby

Replies are listed 'Best First'.
Re: Re: Sub in a Sub & Recursion
by hakkr (Chaplain) on Jan 21, 2002 at 20:19 UTC
    Thanks,
    I've used the closure solution with derby's fix which has given me an insight into a practical use for closures. 'our' worked as well but I've not seen it used here much before and my instinct says to stay away from globalish things.
    Update Cheers for the recursion tips anon monk reads almost like a tutorial. Recursion is a way of thinking I'm determined to bend my head around

      It seems to me, that if you want to use a closure for such a thing, you'll want to use an anonymous sub instead of your FileName sub. Then the @files array will be shared as you expect it to be (e.g., each time Get_Saves is called, $sub will be bound to the new instance of @files).

      sub Get_Saves { my @files; my $sub = sub { unless (($_ eq "." )or ($_ eq "temp.svd")){ push @files, $_; } }; find ($sub,"/usr/local/apache/htdocs/service/"); return \@files, $#files+1; }

      As to how to make two separate subs, derby seems to have already answered that. You'd "need to use either global @files or a lexical @files defined outside of Get_Saves and FileName".

      Hope this helps

      dmm

      If you GIVE a man a fish you feed him for a day
      But,
      TEACH him to fish and you feed him for a lifetime