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

This works:

sub transform { my ($data,$log_fh) = @_; # Localize the log filehandle so all subroutines can see it local *LOG_FH = $log_fh; ... foo($bar); } sub foo { my ($bar) = @_; print LOG_FH "Processing $bar.\n"; ... }

This doesn't:

sub transform { my $data = shift; local $log_fh = shift; ... foo($bar); } sub foo { my ($bar) = @_; print $log_fh "Processing $bar.\n"; ... }

The parent function transform exists in a separate file which is being required by a file that initializes the log filehandle.

Clearly the second case (localizing an indirect filehandle) forces a compile-time error since $log_fh is not a global. Is there a way to do this with an indirect filehandle or is the first method the "best-practice" way to do it? Why would you ever do it as in the perlfaq (open local $fh...)? Am I wrong for trying?

Thanks.

Update: So I should have realized creating a global filehandle at the top of the second case would fix this problem:

our $log_fh; sub transform { my $data = shift; print $log_fh "Processing data $data.\n"; foo("bar"); } sub foo { my ($bar) = @_; print $log_fh "Processing $bar.\n"; } sub main { open ( local $log_fh, '>', 'test.txt' ) or die "Couldn't open log +file\n"; transform( "data", $log_fh ); } main();

If anybody still cares to add to my understanding I'm always grateful.

Replies are listed 'Best First'.
Re: Localizing an indirect filehandle
by Joost (Canon) on Dec 10, 2008 at 18:19 UTC
    If anybody still cares to add to my understanding I'm always grateful.
    FILEHANDLE style file handles are a built-in data type distinct from scalars, hashes, arrays, refs, formats etc. They're also always global (either really global, for the STD* handles, or package-bound).

    $file_handle style handles are real variables and so they get the same scoping / semantics as any other variable, specifically:

    1. local()izing a variable does NOT declare it. IOW, you still need to use our() in whatever scope(s) you use the variable, or use vars.

    2. if you declare the $handle variable to be a lexical, you can't local()ize it either (you can try, but you'll be localizing the package variable of the same name instead).

    3. strict throws an error if you use an undeclared non-automatic global/package variable.

Re: Localizing an indirect filehandle
by chromatic (Archbishop) on Dec 10, 2008 at 21:44 UTC

    Lexical filehandles exist so you don't have to localize global filehandles. I have trouble imagining why you'd need to localize a lexical filehandle.