On 6/15/09 Mon  Jun 15, 2009  12:26 PM, "Thomas H. George"
<li...@tomgeorge.info> scribbled:

> I do not fully understand the solution to the problem, p77-78 & 237.
> 
> First, the declaration of the array my @files in the subroutine
> gather_mtime_between will be read every time find($gather,
> $starting_directories) calls the subroutine.  I take it the repeated
> declarations have no effect and since this is a named subroutine the
> array retains the list from the most previous call.

Each call to the subroutine declares a new, empty array @files. However, the
subroutine gather_mtime_between is only called once, so there is only one
@files array in the scope of gather_mtime_between. There is another array
called @files in the main program, but the two arrays are not the same.

> Second, the statement my $fetcher = sub { @files }; creates an anonymous
> subroutine with the array @files as a return value.

Yes.

> Third, each time the subroutine gather_mtime_between is called by
> find($gather, $starting_directories) it is passed the values $_ and
> File::Find::name for the currectly found file.  When the finds are
> completed the subroutine will be called once more by reference yield.
> On this last call $_ will be undefined so the internal anonymous
> subroutine will return (but no warning message?), the last statment in
> the subroutine is fetcher so the return value of the subroutine is
> @files.

The subroutine gather_mtime_between is not called by the find function. It
is called once by the main program. The two anonymous functions returned by
gather_mtime_between are saved in $gather and $yield. It is the code
reference in $gather that is passed to the find function, resulting in a
call-back to that function for each file and directory found.

> Fourth, the statement in main body my @files = yield->( ): is the last
> call to the subroutine by the reference yield.  As noted in the
> proceeding paragraph the return value is @files so the newly defined
> gobal variable @files receives this value.

This statement is the ONLY call to the subroutine referenced by $yield. It
returns the files saved by the multiple calls to $gather->().

> If all this is obvious as is stated on page 228, please pardon me for
> taking up any readers' time but I would appreciate any confirmation that
> I have thought it through correctly.  If I have it wrong I do need help.
> 
> Just in case anyone takes the time to read all this but is not familiar
> with the problem here is the complete working solution:
> 
>  
> #!/usr/bin/perl -w
> 
> use strict;
> use Time::Local;
> use File::Find;
> 
> my @starting_directory = qw(/data/perl/Intermediate);
> my $total_size = 0;
> my $file_count = 0;
> my $target_dow = 0;
> my $Seconds_per_Day = 60 * 60 * 24;
> my ($sec, $min, $hour, $day, $month, $year, $dow) = localtime;
> my $start = timelocal(0, 0, 0, $day, $month, $year);
> while ($dow != $target_dow) {
> $start -= $Seconds_per_Day;
> if (--$dow < 0) {$dow = 7};
> }
> my $stop = $start + $Seconds_per_Day;
> 
> sub gather_mtime_between {
> my ($begin, $end) = @_;
> my @files;
> my $gatherer = sub {
> my $timestamp = (stat $_)[9];
> unless (defined $timestamp) {
> warn "Cannot find $File::Find::name: $!, skipping\n";
> return;
> }
> push @files, $File::Find::name if
> $begin <= $timestamp && $timestamp <= $end;
> };
> my $fetcher = sub { @files };
> ($gatherer, $fetcher);
> }; 
> 
> my($gather, $yield) = gather_mtime_between($start, $stop);
> find ($gather, @starting_directory);
> my @files = $yield->( );
> 
> foreach my $file (@files) {
> my $mtime = (stat $file)[9];
> my $when = localtime ($mtime);
> print "$when $file\n";
> }
> 



-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/


Reply via email to