2

I am trying to read a file,

    while($line = $file_handle)

When I ran this code, the program hung.

I noticed to read the file using file handle, we need to used <>

   while($line = <file_handle>)

The later code obviously ran.

Now I know operator <> is to read the file line by line, I want to know what exactly is happening when I dont provide <> operator? Is it not able to find the end of the line ?or?

Thankyou

1
  • Without <> you make a copy of $file_handle to $line Commented Jun 1, 2016 at 20:53

3 Answers 3

3

Given this code:

use warnings;
use strict;

open my $fh, '<', 'in.txt' or die $!;

while (my $x = $fh){
    $DB::single=1;
    print "$x\n";
}

when run in the debugger, you can see that $x now contains a GLOB (a copy of the file handle). On each iteration, $x takes the whole handle as an assignment, and causes an infinite loop, because the statement is always true. Because you're always assigning a true value (the handle), the while statement is effectively no different than writing while(1){....

perl -d script.pl

main::(x.pl:4):     open my $fh, '<', 'in.txt' or die $!;
  DB<1> s
main::(x.pl:6):     while (my $x = $fh){
  DB<1> s
main::(x.pl:7):         $DB::single=1;
  DB<1> x $x
0  GLOB(0xbfdae8)
   -> *main::$fh
         FileHandle({*main::$fh}) => fileno(6)
  DB<2> s
main::(x.pl:7):         $DB::single=1;
  DB<2> x $x
0  GLOB(0xbfdae8)
   -> *main::$fh
         FileHandle({*main::$fh}) => fileno(6)

<$fh> essentially extracts a single line from the file handle, and when EOF is hit (or an error occurs), returns undef, which terminates the loop (because undef is false).

Sign up to request clarification or add additional context in comments.

Comments

1

Short   File is read by the <> operator so without it it is only an assignment, thus the infinite loop.


The while (...) { ... } checks the condition inside () and if true it executes the body in the block {}. It keeps doing this until the condition in () evaluates to what is understood as false (generally 0, '0', '', or undef). This is what the operator <> provides, for example, so we have an idiom

while (my $line = <$file_handle>) { ... }

The <> operator reads a line at each iteration from the resource that $file_handle is associated with and when it reaches end-of-file it returns undef so the loop terminates and the program execution continues at the next statement after the loop. The diamond operator <> is the operator form for the function readline. See I/O Operators in perlop. For all this to work $file_handle has to be a valid resource that can retrieve data.

Without the <> operator nothing is read from anywhere, but there is only an assignment. The code does the following. It copies the variable $file_handle into the variable $line. The return value of that operation in Perl is the value that ends up in $line, and if that is a 'truthy' value then the body { ... } is executed. The $file_handle clearly evaluates to 'true', otherwise the loop body would not execute even once and the program would continue. Thus $line is true, too. So if the $file_handle doesn't change in the body {...} of the loop the condition is always true.

Then whatever is in the body keeps being executed, without a reason for the loop to terminate, and it thus never returns control to the program. It's an infinite loop, and the program appears to hang.


Note that this is sometimes used deliberately and you may see code like

while (1) {
    # Compute what is needed
    # Recalculate the condition for when to stop
    last if $condition_to_terminate;
}

This approach can be risky though, since the condition can get more and more complicated and an error could sneak in, in which case we end up with an infinite loop. There are usually clearer ways to control loops.

A completely different example is an event loop, where it is crucial to enter an infinite loop so that we can then wait for an event of some sort, at which point a particular action is taken. This is how GUI's work, for example, and a number of other systems.

Comments

0

For the example that 'hung':

while($line = $file_handle)

The elements $line = $file_handle is purely an assignment. At that point, your while is just checking that the assignment is truthy, i.e. that $line is not the number 0, the string 0, an empty string, or undef, which of course it's not -> hense you get an infinite loop.

1 Comment

"your while is just checking that the assignment happened" Actually, it's checking that the return value of the scalar assignment operator is truthy, i.e. that $line is not the number 0, the string 0, the empty string, or undef.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.