Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Re: lexical vs. local file handles

by haukex (Bishop)
on Apr 18, 2020 at 19:04 UTC ( #11115735=note: print w/replies, xml ) Need Help??


in reply to lexical vs. local file handles

Do I miss something here? Do you see any pitfalls using this approach?
  • When you localize a glob, you're localizing every variable with that name - scalars, arrays, hashes, etc.
  • local's effects have dynamic scope, so they effect everything called in that scope, including code that might not be yours. You might step on someone else's globals, or they might step on yours. The major issue is that this is action at a distance: things may break in remote pieces of code, and it may be incredibly hard to connect the problem to the cause. This will not happen with lexicals.
  • Bareword filehandles also clash with package names (see also).
  • Update from here: open local *HMD, ">", \(my $x) or die $!; print HND "Foo"; close HND; only causes warnings, while open my $hmd, ">", \(my $x) or die $!; print $hnd "Foo"; close $hnd; is a compile-time error.
use warnings; use strict; our $FH = "Hello, World!"; sub FH::awesome { print "<$FH>\n" } FH->awesome; open local *FH, "<", \my $x or die $!; FH::awesome; # => Use of uninitialized value $FH in concatenation (.) or string FH->awesome; # => Can't locate object method "awesome" via package "IO::File"
Though there are good reasons for this, it has a drawback. Filehandles in Perl are special on a syntactical level. The compiler is capable of catching errors like this:

You seem to be naming only a single (IMHO minor) advantage, compared to all the arguments against bareword filehandles. Unless there's something else I'm missing, for me, the arguments against bareword filehandles outweigh those in favor of them.

Instead of using bareword filehandles, you could get into the practice of being explicit about your prints, as in print {$fh} "something\n"; - visually a whole lot more clear. (Update: see also Perl::Critic::Policy::InputOutput::RequireBracedFileHandleWithPrint.)

See also "open" Best Practices.

Update 2: Just to cross-reference this thread to another lexical vs. bareword filehandle discussion: Re^2: Summing numbers in a file

Replies are listed 'Best First'.
Re^2: lexical vs. local file handles
by jo37 (Pilgrim) on Apr 18, 2020 at 19:40 UTC

    Hi haukex

    thank you for your comments. I'm not fully convinced yet, though.

    When you localize a glob, you're localizing every variable with that name - scalars, arrays, hashes, etc.
    Sure. But I can keep a reference to those if needed. Or I can choose a different name for the file handle.
    local's effects have dynamic scope, so they effect everything called in that scope, including code that might not be yours. You might step on someone else's globals, or they might step on yours. The major issue is that this is action at a distance: things may break in remote pieces of code, and it may be incredibly hard to connect the problem to the cause. This will not happen with lexicals.
    As shown in my example, the usage in another package does no harm.
    Bareword filehandles also clash with package names (see also).
    Is this an issue occuring in real life? Probably I do not understand this in all detail yet.

    Still using barewords :-)

    Greetings,
    -jo

    $gryYup$d0ylprbpriprrYpkJl2xyl~rzg??P~5lp2hyl0p$

      It's probably possible to make localized bareword filehandles work, if you take a whole lot of care to avoid all the issues. But then again, you could be spending all that care on avoiding print $fh, "", couldn't you? (You could probably even write a Perl::Critic policy to avoid it - Perl::Critic::Policy::InputOutput::ProhibitBarewordFileHandles already exists.) I guess I should have worded my point above as a question:

      Other than catching the print FH, "" issue, what advantages to using bareword filehandles do you see over lexical filehandles?

      Edit: Added link to module.

        My point is: bareword filehandles are something special in Perl syntactically. Avoiding them cuts off a part of the language.

        Greetings,
        -jo

        $gryYup$d0ylprbpriprrYpkJl2xyl~rzg??P~5lp2hyl0p$
      I'm not fully convinced yet, though.

      Here's one more: open local *HMD, ">", \(my $x) or die $!; print HND "Foo"; close HND; only causes warnings, while open my $hmd, ">", \(my $x) or die $!; print $hnd "Foo"; close $hnd; is a compile-time error. Warnings are easily missed in server logs or long command-line outputs.

      Sure. But I can keep a reference to those if needed. Or I can choose a different name for the file handle.

      Taken all together, doesn't it all seem to be getting a bit complicated? You've got quite a long list of things you need to keep track of: in the entire scope of the local (which you have to put in its own block to limit its scope), that is, the entire call stack, you have to know all of the names of the globs and packages that you're working with, and you have to be sure they don't clash with each other or anything else (your sub close_fh is just one example), plus you have to keep track of possible typos. None of these are things to worry about when you use lexical filehandles.

      Is all that really worth it to avoid the print $fh, typo? (If you're only ever going to be writing short command-line scripts that don't write much to STDOUT/ERR or call anyone else's code, maybe yes...?)

        Nitpicking on the HMD/HND example: It gives a compile time error, too.

        I haven't answered your question about the "why" yet.

        There is this special member of the Perl ecosphere called filehandle. It is special, it needs to be treated special and it is eye-catching. Beneath scalars, arrays, hashes and subs it is something "primal" in Perl. I just like filehandles and I thought they were there to be used.

        OTOH, reflecting all your points makes me thoughtful. Using the idiom given by Your Mother in Re: lexical vs. local file handles solves the one case where a bareword seemed to be of advantage.

        I really should abandon this habit. Thanks for your input and your patience.

        Greetings,
        -jo

        $gryYup$d0ylprbpriprrYpkJl2xyl~rzg??P~5lp2hyl0p$

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (4)
As of 2020-09-30 04:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    If at first I donít succeed, I Ö










    Results (158 votes). Check out past polls.

    Notices?