V
Veli-Pekka Tätilä
Hi,
I'm playing around with tied filehandles at the moment. Now that I'm finally
beginning to grasp the basics of Perl OOP, tying doesn't seem all that
difficult. The only problem is, I cannot, for the life of me, figure out how
to tie lexically scoped handles or IO::File objects. I'd like to hold my
file handles in lexically scoped scalars be them globrefs or objects. I've
read perltie and perlref, browsed the Perl FAQ and Googled both the groups
and the Web with little success.
In the interest of simplicity, I won't be showing my real code here, but a
short test script demonstrating the problem. Here's a very basic tied handle
example slightly adapted from the perltie man-page (I had to add one my in
it):
use strict; use warnings;
package Shout;
sub TIEHANDLE { print "<shout>\n"; my $i; bless \$i, shift }
sub PRINT
{
no warnings 'uninitialized'; # $\ tends to be undef.
my $r = shift; $$r++;
print join($,,map(uc($_),@_)),$\
}
sub CLOSE { print "CLOSE called.\n" }
sub DESTROY { print "</shout>\n" }
And now the test program (actually in the same file):
package main;
# Only the first sub is succesful, the rest attempt calling TIESCALAR and
die.
oldschool(); lexical(); oop();
The first of the Strategies looks like this:
sub oldschool
{ # Local type globs.
local *FH;
tie *FH, 'Shout';
print FH "Tie Fighter\n";
close FH;
} # sub
This strategy works well, calling TIEHANDLE, PRINT, CLOSE AND DESTROY as
expected. The output is:
<shout>
TIE FIGHTER
CLOSE called.
</shout>
However, I like this filehandle syntax the least of the bunch.
My second approach goes like this:
sub lexical
{ # Typeglob refs in scalars.
use Symbol 'gensym';
my $fh;
$fh = gensym;
# open my $fh, '>test.dat' or die $!;
tie $fh, 'Shout';
print $fh "X-Wing\n";
} # sub
The only major difference is using gensym to generate a reference to an
anonymous typeglob held in a scalar. The second method dies with the
message:
Can't locate object method "TIESCALAR" via package "Shout"
Whether the file handle is generated with gensym or derived by passing open
an undef scalar appears to make no difference. That is in both cases it
seems tie looks at its args, determines that the first is a scalar and
assumes I'd liek to tie a scalar. Although quite logical, in a way, I would
have expected it to handle filehandles as diversly as print et al do.
The third and final method is the same as the second, except that we use a
scalar holding an IO::File object. Again tie infers that I'd like to tie a
scalar and the problem persists. For completeness, here's the code:
sub oop
{ # The object-oriented interface.
use IO::File;
my $fh = IO::File->new;
tie $fh, 'Shout';
print $fh "Death Star\n";
} # sub
I can, of course, use localized file handles for a solution that works. I
would dearly liek to use some safer variant, however. For simple stuff,
lexically scoped file handles gotten from open are my favorite.
Any help greatly appreciated.
PS: Perl version is 5.8.8 on Win XP Pro SP2.
I'm playing around with tied filehandles at the moment. Now that I'm finally
beginning to grasp the basics of Perl OOP, tying doesn't seem all that
difficult. The only problem is, I cannot, for the life of me, figure out how
to tie lexically scoped handles or IO::File objects. I'd like to hold my
file handles in lexically scoped scalars be them globrefs or objects. I've
read perltie and perlref, browsed the Perl FAQ and Googled both the groups
and the Web with little success.
In the interest of simplicity, I won't be showing my real code here, but a
short test script demonstrating the problem. Here's a very basic tied handle
example slightly adapted from the perltie man-page (I had to add one my in
it):
use strict; use warnings;
package Shout;
sub TIEHANDLE { print "<shout>\n"; my $i; bless \$i, shift }
sub PRINT
{
no warnings 'uninitialized'; # $\ tends to be undef.
my $r = shift; $$r++;
print join($,,map(uc($_),@_)),$\
}
sub CLOSE { print "CLOSE called.\n" }
sub DESTROY { print "</shout>\n" }
And now the test program (actually in the same file):
package main;
# Only the first sub is succesful, the rest attempt calling TIESCALAR and
die.
oldschool(); lexical(); oop();
The first of the Strategies looks like this:
sub oldschool
{ # Local type globs.
local *FH;
tie *FH, 'Shout';
print FH "Tie Fighter\n";
close FH;
} # sub
This strategy works well, calling TIEHANDLE, PRINT, CLOSE AND DESTROY as
expected. The output is:
<shout>
TIE FIGHTER
CLOSE called.
</shout>
However, I like this filehandle syntax the least of the bunch.
My second approach goes like this:
sub lexical
{ # Typeglob refs in scalars.
use Symbol 'gensym';
my $fh;
$fh = gensym;
# open my $fh, '>test.dat' or die $!;
tie $fh, 'Shout';
print $fh "X-Wing\n";
} # sub
The only major difference is using gensym to generate a reference to an
anonymous typeglob held in a scalar. The second method dies with the
message:
Can't locate object method "TIESCALAR" via package "Shout"
Whether the file handle is generated with gensym or derived by passing open
an undef scalar appears to make no difference. That is in both cases it
seems tie looks at its args, determines that the first is a scalar and
assumes I'd liek to tie a scalar. Although quite logical, in a way, I would
have expected it to handle filehandles as diversly as print et al do.
The third and final method is the same as the second, except that we use a
scalar holding an IO::File object. Again tie infers that I'd like to tie a
scalar and the problem persists. For completeness, here's the code:
sub oop
{ # The object-oriented interface.
use IO::File;
my $fh = IO::File->new;
tie $fh, 'Shout';
print $fh "Death Star\n";
} # sub
I can, of course, use localized file handles for a solution that works. I
would dearly liek to use some safer variant, however. For simple stuff,
lexically scoped file handles gotten from open are my favorite.
Any help greatly appreciated.
PS: Perl version is 5.8.8 on Win XP Pro SP2.