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

I was updating an old script and came across a slight change in behaviour when changing two-argument opens with bareword filehandles to three-argument ones with indirect filehandles. The script used the common idiom

while (<IN>) { print OUT; }

but when converted to

while (<$inFH>) { print $outFH; }

I get a series of GLOB(0x180834) strings printed to STDOUT. The print does not seem to recognise the scalar as a filehandle in this situation and prints it's contents instead. Doing

while (<$inFH>) { print $outFH $_; }

gets around the problem but it seems a pity that such a common behaviour no longer works. I have looked at the documentation but can't see anything describing this behaviour. Am I missing something obvious?

Cheers,

JohnGG

Replies are listed 'Best First'.
Re: Bareword vs. Indirect Filehandle behaviour
by shmem (Chancellor) on Sep 19, 2006 at 10:04 UTC
    The obvious you're missing is that
    print OUT;
    is just relying on yet another perl Do-What-I-Mean feature. The bareword OUT happens to be a filehandle, and the statement resolves to a bare print statement (to that filehandle). A bare print results in printing $_.

    In fact, a bareword after print is always interpreted as a filehandle1, no matter if it exists:

    $ perl -wle 'print OUT' Name "main::OUT" used only once: possible typo at -e line 1. print() on unopened filehandle OUT at -e line 1.
    With indirect filehandles that isn't the case: here the filehandle is a scalar holding a reference to a glob. Perl can't figure out what you mean (and imho ought not, anyways), so your variable's content gets printed. Only with print $expr LIST inspection of $expr is done.

    <update>

    $ perl -wle 'print $fh' Name "main::fh" used only once: possible typo at -e line 1. Use of uninitialized value in print at -e line 1. $ perl -wle 'print $fh $bar' Name "main::bar" used only once: possible typo at -e line 1. Name "main::fh" used only once: possible typo at -e line 1. Can't use an undefined value as a symbol reference at -e line 1.

    Only in the latter case perl tries to resolve $fh to a filehandle.

    1) unless your bareword is a constant as in

    $ perl -wle 'use constant OUT => "foo";print OUT' foo
    </update>

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      Perl can't figure out what you mean (and imho ought not, anyways) ...

      I was sort of hoping that it could figure out what I mean because I think the while (<IN>) {print OUT;} construct is one of the neater features of the language. If I substitute an indirect filehande for a bareword one I still mean it to be a filehandle and give the same behaviour. Adding the $_ is no big deal but the new behaviour breaks an idiom that I would guess is familiar to most and widely used.

      Cheers,

      JohnGG

        Just one opinion, but I think your asking perl to extend an idiom rather than to not break one. The old idiom is still there.

        For me, it would be quite confusing if Perl extended the idiom so that "print $outFH;" was a write of "$_" to a specified filehandle, rather than a write of a variable to STDOUT. I have no doubt Perl could get it right, because it knows what variables are file handles and what aren't. I'd just have trouble reading it without my eyes getting caught in the wrong mode; I'd have to mentally back-track each time I read it.

Re: Bareword vs. Indirect Filehandle behaviour
by ikegami (Patriarch) on Sep 19, 2006 at 15:50 UTC

    Also,
    print { $outFH } $_;
    works, but
    print { $outFH };
    gives a compile error.