CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
Search Posts SEARCH
Who's Online WHO'S
Log in LOG

Home: Fun With Perl: Perl Quizzes - Learn Perl the Fun Way:
An iterator



Mar 11, 2001, 10:26 AM

Post #1 of 4 (55859 views)
An iterator Can't Post

This is part of a program I am writing to play with my website's log files that live in 'logdir'. For right now it will just print the line as is (line 14) but that will change soon. If it helps you to think about the problem (and to answer question 8B), the contents of the directory are logs from two months (2001_01.log and 2001_02.log).

There are several questions of varying difficulty so everyone should have a chance to play. But the important questions are 13A and 13B.

 1  #!/usr/local/bin/perl 
3 use strict;
5 my $dirname = 'logdir';
7 opendir (DIR, $dirname) or die "could not open dir, $!\n";
8 my @files = sort map {"$dirname/$_" } grep { !/^\.+$/ } readdir DIR;
9 closedir DIR;
11 my $it = make_iterator(@files);
13 while (my $line = $it->()) {
14 print $line;
15 }
17 sub make_iterator
18 {
19 my (@datafiles) = @_;
21 return unless @datafiles;
23 my $fh = do { local *FH };
24 while (@datafiles) {
25 my $file = shift (@datafiles);
26 (open ($fh, $file))
27 ? last
28 : print STDERR "failed to open $file, $!\n"
29 }
31 my $iterator =
32 sub {
33 my $line;
34 return $line if ($line = <$fh>);
36 while (@datafiles) {
37 close $fh;
38 my $file = shift (@datafiles);
39 unless (open ($fh, $file)) {
40 print STDERR "failed to open $file, $!\n";
41 next;
42 }
43 return $line if ($line = <$fh>);
44 }
45 return;
46 };
47 return $iterator;
48 }

And now the questions...

Line 8
8A) Why is the grep here?
8B) What ends up in @files when the line is finished?

Line 23
23A) What is going on here?

Lines 24-29
24A) When it finishes looping, what do will $fh do for us?

Lines 31-32, 46-47, and 11
31A) What is the name for this type of structure?
31B) What is being returned?
31C) Why are lines 33-44 allowed to use $fh and @datafiles?

Line 34 and 43
34A) What will be returned?

Lines 36-42
36A) What will cause this while to do the next and skip to the next datafile?
36B) What will cause the loop to not exit at line 43 and move to the next datafile?

And the big picture question. I have jumped through many hoops to make line 13 work, so...

Line 13
13A) What does it do?
13B) Why was it worth all the effort?

As an attachment to this message you can get the code without the line numbers.

Sun Sep 9, 2001 - 1:46:40 GMT, a very special second in the epoch. How will you celebrate?


Mar 15, 2001, 7:40 AM

Post #2 of 4 (55842 views)
Re: An iterator [In reply to] Can't Post

8A. To filter out the directories '.' and '..'
8B. @files contains 'logdir/filename' for all of the files in the $dirname and 'logdir/subdirname' for all directories (except '.' and '..') in $dirname.

23A. A 'do' block is executed. Inside the block is a local variable (a glob). Since the glob is the last value of the block, and a local variable, $fh is assign to be the glob that will refers to anything named FH (filehandles, arrays, scalars, etcetera).

24A. Loops through all of the files in @datafiles and attempts to open each one. It prints an error message for each failed open. On a successful open $fh refers to the successfully opened file and the loop stops.

31A. A Subroutine Reference
31B. A reference to a subroutine is returned.
31C. Because the subroutine definition is w/i the scope of the subroutine 'make_iterator' it can reference $fh and @datafiles.

34A. A line of data from the currently open file will be returned.

36A. A file failing to open.
36B. If there is no data in the currently open file.

13A. Calls the subroutine referenced by $it. Test to see if the returned value, $line, is true (has data and not 'eof'). Prints the $line if not 'eof'.
13B. It was worth the effort so you can keep from passing the exact same data to two separate subroutines in separate calls. This way they can share the data.


Mar 27, 2001, 9:03 PM

Post #3 of 4 (55817 views)
Re: An iterator [In reply to] Can't Post

That about sums it up. Except for 31A. I was really looking for 'closure'.

I know there is a section on closures in the camel book, but I have not found a good link to include here to make it easy.

Also it has been pointed out to me that by using a trick with one of perl's built-in variables this can be simplified greatly (to about 9 lines). So if anyone is feeling creative you have another chance to show off.

Sun Sep 9, 2001 - 1:46:40 GMT, a very special second in the epoch. How will you celebrate?


Mar 28, 2001, 7:31 AM

Post #4 of 4 (55814 views)
Re: An iterator [In reply to] Can't Post

I wrote an article that has a section on closures. Using Closures.

Jeff "japhy" Pinyan -- accomplished hacker, teacher, lecturer, and author


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives