Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

eof not recognised when applying diamond operator to invocation arguments?

by pat_mc (Pilgrim)
on Jan 12, 2011 at 16:23 UTC ( #881934=perlquestion: print w/ replies, xml ) Need Help??
pat_mc has asked for the wisdom of the Perl Monks concerning the following question:

Esteemed Monks -

I am puzzled and hope your wisdom can enlighten me. I have written a short test programme to study an unexpected behaviour and do not understand why it is behaving the way it is:

for my $input_file ( @ARGV ) { while ( ! eof ) { print <>; } print "=========SEPARATOR: Processing $input_file =========\n"; }
I know this might be an unusual way to write things, but this is just a reduction of another programme which necessitated this kind of code structure.

What I am finding is that when I invoke the script with two argument files, it prints the separator once - not inbetween the contents of the first and the second file but at the end of the second file. I would have expected it to print the contents of the first file, then the separator, then the contents of the second file and the separator again. Also, the separator listed the name of the first argument file instead of that of the second file. Why did it do that??

Thanks for your help in advance!

Cheers -

Pat

Comment on eof not recognised when applying diamond operator to invocation arguments?
Download Code
Re: eof not recognised when applying diamond operator to invocation arguments?
by Anonymous Monk on Jan 12, 2011 at 16:36 UTC
    <> slurps both files at once.
    # echo FOO > foo # echo BAR > bar # perl -wE'say <>; say "Done";' foo bar FOO BAR Done #
      Yep ... that's obviously correct. My question was 'WHY'. I would have assumed that the end-of-file information does not get lost when I used the diamond operator to read the input files line by line. Why is the code I posted not behaving equivalently to
      while( <> ) { print; print "========================== Now at $ARGV =================== +=======\n" if eof; }
      which prints the contents of the first file, then the separator, then the contents of the second file and the separator again.
        Why is the code I posted not behaving equivalently to ...

        because in your original code the eof is tested only once before everything is being read and output.  In the second case, it's tested for every line, so it has a chance to detect the end-of-file conditions.

Re: eof not recognised when applying diamond operator to invocation arguments?
by Illuminatus (Curate) on Jan 12, 2011 at 16:43 UTC
      Hm ... thanks, Illuminatus ... I looked at that link ... not sure it provided me with the answer (or at least - if it did, I did not get it). Could you please be a little more verbose? Your wisdom will be much appreciated!

      Pat
        When you do not explicitly open the files by name, but simply start using <>, you are reading a catenation of all of the files on the command line. Therefore, the first time through the loop, you read all of the files. As the link implied, $ARGV refers to whatever file <> is currently referencing (the last one). If you want it to work as you intend, you could do something like:
        foreach my $file (@ARGV) { open (FILE, $file) || die "could not open $file"; while (<FILE>) { print $_; } close FILE; print "whatever you wanted to use as a separator $file\n"; }

        fnord

Re: eof not recognised when applying diamond operator to invocation arguments?
by Anonyrnous Monk (Hermit) on Jan 12, 2011 at 17:58 UTC

    Just in case you're curious...  If you wanted to stick with your original code as closely as possible, here's how you'd have to modify it to get it working as desired (I wouldn't recommend it though):

    my @filesnames = @ARGV; for my $input_file ( @filesnames ) { eof(); while ( ! eof ) { print scalar <>; } print "=========SEPARATOR: Processing $input_file =========\n"; }
      Why wouldn't you recommend to use this code?

        Mainly because it's unnecessarily hard to understand:  eof(); WTF?  Why does it have to be before the loop? If you move it after the loop, it will work with Perl 5.12 just fine, too, but not with 5.10.  Also, someone (including yourself) looking at this later might figure the additional array @filenames is superfluous (and remove it), etc.

        Any compelling reason you can't use the more direct version you mentioned yourself elsewhere in the thread?

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://881934]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (5)
As of 2014-12-28 08:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (179 votes), past polls