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/