I'd like to pass a reference to a file handle to a subroutine, such that code in the sub can read from the file and the position in the file handle changes in the calling environment, rather like using a pointer in C.
This kind of thing:
open my $fh, '<', $somefile or die;
dosomething(\$fh);
sub dosomething
{
my $fh_ref = shift;
while (my $l = <$$fh_ref>)
{
print $l;
print "\n";
}
}
This gives this output instead of writing each line:
GLOB(0x20b8b38)
Obviously I am dereferencing the file handle reference wrong.
Addendum:
while (my $l = readline($$fh_ref))
{
etc.
seems to do the trick. I am still interested in why the first approach doesn't work.
The diamond operator <...>
has two meanings in Perl -- one corresponding to the readline(HANDLE)
function and the other corresponding to glob(EXPR)
. How does perl decide which function to use?
If what's within the angle brackets is neither a filehandle nor a simple scalar variable containing a filehandle name, typeglob, or typeglob reference, it is interpreted as a filename pattern to be globbed, and either a list of filenames or the next filename in the list is returned, depending on context. This distinction is determined on syntactic grounds alone. That means
<$x>
is always areadline()
from an indirect handle, but<$hash{key}>
is always aglob()
. That's because$x
is a simple scalar variable, but$hash{key}
is not--it's a hash element. Even<$x >
(note the extra space) is treated asglob("$x ")
, notreadline($x)
.
The workarounds are to either use an explicit readline
call
while (my $l = readline($$fh_ref)) ...
or to use a simpler expression inside the brackets.
my $fh42 = $$fh_ref;
while (my $l = <$fh42>) ...