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

Hi Monks,

I have a simple program that passes a file handle as the only argument to a subroutine. <$_[0]> fails to return a line from the file. Instead, it returns something like "GLOB(0x1bcb22a0)". However, if I use another variable to store the file handle. It works!

Anyone has any idea?

#!/usr/bin/perl -w use strict; use warnings; open my $FH, "/tmp/test.txt" || die "Failed to open /tmp/test.txt: $!\ +n"; ## NOT WORKING !! while (my $Line = GetLine($FH)) { print "$Line"; } ## NOT WORKING !! sub GetLine { my $line = <$_[0]> ; return $line; }

If I change the subroutine GetLine to the codes below. It works.

sub GetLine { my $FH = shift; my $line = <$FH> ; return $line; }

Replies are listed 'Best First'.
Re: $_[0] fails for file handle?
by jwkrahn (Abbot) on Jul 17, 2012 at 04:45 UTC

    That is because the <> operator has two functions.    my $line = <$_[0]> ; is the same as my $line = glob "$_[0]" ; while my $line = <$FH> ; is the same as my $line = readline $FH ;

      Thanks for your reply. That explains the myth!

Re: $_[0] fails for file handle?
by AnomalousMonk (Archbishop) on Jul 17, 2012 at 17:03 UTC
    open my $FH, "/tmp/test.txt" || die "Failed to open /tmp/test.txt: $!\ +n";

    BTW: This statement from the OP has a bug. The relatively high precedence of the  || logical-or operator means that the truth value of the file name is logical-ored with the value returned by the die built-in (which, of course, never returns). Because a file name will almost always be true ('0' is the only one I can think of that would be false), the short-circuiting of the  || operator means that  die will almost never be evaluated and the statement will seem to 'work'. The  or logical operator has a sufficiently low precedence to make this really work. (See perlop.)

    So the correct version of this idiom is something like
        open my $FH, "/tmp/test.txt" or die "Failed to open /tmp/test.txt: $!\n";
    or (less elegantly IMHO)
        open(my $FH, "/tmp/test.txt") || die "Failed to open /tmp/test.txt: $!\n";

    Update: This bug is hinted at by the fact that in the deparse of toolic's reply, the  die sub-expression has vanished! This is because the literal file name  "/tmp/test.txt" is always true, so the compiler softly and silently optimizes the  die away.

Re: $_[0] fails for file handle?
by toolic (Bishop) on Jul 17, 2012 at 13:12 UTC
    You already have your answer, but here is a method to finding that answer.

    Tip #6 from the Basic debugging checklist: Check to see if your code is what you thought it was: B::Deparse

    use warnings; use strict 'refs'; open my $FH, '/tmp/test.txt'; while (my $Line = GetLine($FH)) { do { print "$Line" }; } use File::Glob (); sub GetLine { use warnings; use strict 'refs'; my $line = glob($_[0]); return $line; }