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

Dear Monks,

In my program I have a bit of code like the following:
for(;;) { begining: print "A\n"; foreach my $job (read_dir("G:/Input")) { print "B\n"; next unless $job =~ /(.{1,36})\.txt$/; my $tag = $1; ##'when you have checked all the files' GOTO beginning foreach my $job (read_dir(G:/Output")) { print "D\n";
This program runs in the background of my PC and picks up request files and then runs with them. But occassionally it will get caught in a loop at the stage where it says print 'B'; It will then pull out of the loop and continue as before only when I press Control-C at the DOS prompt. I am wondering whether the solution to this problem is to say 'when you have checked all the files' GOTO beginning: ? Does anyone have any suggestions about what is causing this and how best it can be fixed?

Replies are listed 'Best First'.
Re: Caught in a loop
by halley (Prior) on Oct 14, 2005 at 16:12 UTC
    Since your pseudocode isn't actually code, we can't check much for you. Missing quotes, bad syntax, partial program, etc. Are you even within a use strict; use warnings; context?

    One, you are using my $job to control two nested loops. Bad form, and probably won't do what you want, unless you really know the difference between local and my. Maybe this is the cause of your hangup.

    Two, instead of a goto and a generic label, you may be interested to know that perl's next accepts a label, and loop structures can be specifically labeled.

    TASK: for my $task (@tasks) { my @files = get_files_for_task($task); FILE: for my $file (@files) { # whatever next TASK if file_is_bad($file); next if file_is_complete($file); # same as next FILE } }

    --
    [ e d @ h a l l e y . c c ]

Re: Caught in a loop
by cbrandtbuffalo (Deacon) on Oct 14, 2005 at 15:57 UTC
    I don't know if it will solve your problem or not, but for the type of thing you're doing I would think a 'while' would be more appropriate. I tend to think of 'for' loops as being more deterministic, and your situation is more open ended. So maybe something like:
    while(1) { begining: print "A\n"; while (my $job = read_dir("G:/Input")) { print "B\n"; next unless $job =~ /(.{1,36})\.txt$/; my $tag = $1; ##'when you have checked all the files' GOTO beginning while (my $job = read_dir(G:/Output")) { print "D\n";
    I'm interested to hear from some other monks.
Re: Caught in a loop
by 5mi11er (Deacon) on Oct 14, 2005 at 16:01 UTC
    Without the rest of the code within the loops, it becomes more of a guessing game, but I'll give it a shot.

    My first guess is that a file is placed in the Input directory that doesn't match your regular expression, and as long as that is true, B is going to continue to be printed. Why it might "pull out" when you hit control-C, I couldn't say...

    -Scott

Re: Caught in a loop
by graff (Chancellor) on Oct 15, 2005 at 15:56 UTC
    This seems like one of those cases where a better understanding of the overall task would really help. Based on the fragments in the OP when I read it, the basic idea seems to be something like this:

    On a continuous basis (running constantly):

    1. Check G:/Input to see if there are any files whose names are 1 to 36 characters long and have a ".txt" extension.
    2. For each file detected in step 1, check G:/Output for ... (?)
    3. ?? ... (something involving a particular file (subset) in G:/Output? or something involving the current file from G:/Input if there is no matching file in G:/Output? or something for every pairing of files in the two directories?)

    If your overall goal for this app can be described in such terms, there may be much better ways to do this than nested for loops. But I don't know what to suggest, because I don't know what you really want to do.