Re: Passing filehandles to subroutines
by Paladin (Vicar) on Jan 27, 2003 at 04:50 UTC
|
my $handle = new IO::File "> $outfile";
print_stuff_to($handle);
sub print_stuff_to {
my $fh = shift;
print $fh "Foo Bar";
}
| [reply] [Watch: Dir/Any] [d/l] |
Re: Passing filehandles to subroutines
by John M. Dlugosz (Monsignor) on Jan 27, 2003 at 06:53 UTC
|
I never use global file-handle identifiers any more. Without pulling in the whole File::IO module, you can still do this:
open (my $in, $infile) or die;
foo ($in);
sub foo
{
my $file= shift;
print $file "Some Stuff."; # note no comma
}
Basically, a reference to a glob can be used just like a glob to mean the associated file handle. In Perl 5.6 I think the open function will auto-vivify to just that, so you don't need to use a module or tricks to create a reference to an anonomous glob anymore. There's been discussions on that here; I posted a question concerning using this as the prefered method moving forward, when I heard about the auto-vivification.
—John | [reply] [Watch: Dir/Any] [d/l] |
|
John,
This is very cool. I like this method. Do you have any idea if this is going to be supported in Perl 6? Or, perhaps I should ask, is this 'kosher'? This isn't a "may be removed if we feel like it" feature, is it?
Thanks!
ibanix
$ echo '$0 & $0 &' > foo; chmod a+x foo; foo;
| [reply] [Watch: Dir/Any] [d/l] |
|
See if you can find my thread via super search or skimming the list of nodes I posted. That is when I asked if it was 'kosher' and got a lot of remarks about it. What I remember: yes, it is proper and will work moving forward, but doesn't work on older versions (I don't remember when) so it is an issue if you need to run on older stuff, but no other issues impressed me enough to remember or disuade me.
—John
| [reply] [Watch: Dir/Any] |
|
|
It's pretty normal as far as I know, I use it all the time. Look at the perlsub documentation about passing around filehandles.
C.
| [reply] [Watch: Dir/Any] |
Re: Passing filehandles to subroutines
by BrowserUk (Patriarch) on Jan 27, 2003 at 05:32 UTC
|
Besides IO::File which probably has other advantages, you can also pass globs by prefixing the name with *. Eg.
sub myprint { my $fh = shift; print $fh $_[0]; }
...
open OUT, '>', 'junk' or die $!;
myprint *OUT, 'test';
close OUT;
c:\test>type junk
test
c:\test>
Examine what is said, not who speaks.
The 7th Rule of perl club is -- pearl clubs are easily damaged. Use a diamond club instead. | [reply] [Watch: Dir/Any] [d/l] |
Re: Passing filehandles to subroutines
by tall_man (Parson) on Jan 27, 2003 at 05:46 UTC
|
I think IO::File is the best way to go, but there is another way if you really don't want to change your "OUT" style filehandles in the main code. You can pass references to typeglobs into subroutines, like this:
print_some_stuff(\*OUT);
sub print_some_stuff {
my $fh = shift;
print $fh "stuff\n";
}
| [reply] [Watch: Dir/Any] [d/l] |
Re: Passing filehandles to subroutines
by Aristotle (Chancellor) on Jan 27, 2003 at 11:41 UTC
|
As already mentioned, on Perl 5.6+ you can simply
open my $fh, "<", $filename;
and then pass $fh around. If you want to be compatible with earlier versions, it is only slightly more verbose:
use Symbol qw(gensym);
# ...
open +(my $fh = gensym), "<$filename";
And yes, this is definitely going to stay with us in Perl 5. In Perl 6 you'll be doing things entirely differently:
my $fh = open "<", $filename;
Though the other syntax will probably remain supported. Still I'm definitely switching to this new construct as soon as possible.
Makeshifts last the longest. | [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Passing filehandles to subroutines
by rdfield (Priest) on Jan 27, 2003 at 10:08 UTC
|
I know this isn't strictly answering the question, but after a lot of pondering I came to the conslusion that removing the filehandle from the print, and selecting the correct filehandle increased the functionality of my code dramatically.
For instance, say I have a function that generates HTML, I can (a) use it 'vanilla' style under a webserver and get a webpage, (b) tie a filehandle to a scalar, select it and manipulate the resultant HTML programmatically, or (c) select a normal filehandle for placement into a content management hierarchy (or whatever). Same function, different results. rdfield | [reply] [Watch: Dir/Any] [d/l] |
|
| [reply] [Watch: Dir/Any] |
|
I knew I'd come up with a concrete counter-example eventually :)
I use Pod::HTML in a mod_perl handler to generate "Help" screens on the fly when a user clicks on the Help menu item in my CGI application. The module uses a named filehandle, which when used in "interactive" mode is opened against "". Works great from the command line - but completely baulks under mod_perl. Back to the drawing board: I worked around it by supplying it with a temporary (session based) file name, and then reading the resultant file and printing it to (what appears to be) STDOUT. rdfield
| [reply] [Watch: Dir/Any] [d/l] |
|
|
|
Re: Passing filehandles to subroutines
by artist (Parson) on Jan 27, 2003 at 15:39 UTC
|
Based on various suggestion received here, here is the tested code.
use strict;
use warnings;
my $outfile = "test.txt";
open (my $ofh, ">$outfile") or die;
foo ($ofh); #Prints to the file pointed by $ofh
foo(); #Prints to STDOUT
sub foo
{
my $filehandle= shift;
$filehandle ||= \*STDOUT ;
select($filehandle);
print <<"EOF";
This is a test, it is only a test.
In the event of an emergency, run around in a panic.
EOF
}
artist | [reply] [Watch: Dir/Any] [d/l] |