Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

Re^2: Best way to check if something is a file handle?

by tobyink (Abbot)
on Jul 09, 2012 at 08:30 UTC ( #980672=note: print w/replies, xml ) Need Help??

in reply to Re: Best way to check if something is a file handle?
in thread Best way to check if something is a file handle?

Practical experimentation shows this doesn't work. :-(

use 5.010; use Test::More; use IO::Handle; open my $fh, ">", "/tmp/foo" or die "argh"; ok $fh->can("close"); ok UNIVERSAL::can($fh, "close"); done_testing(); __END__ not ok 1 # Failed test at line 7. not ok 2 # Failed test at line 8. 1..2 # Looks like you failed 2 tests of 2.
perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'

Replies are listed 'Best First'.
Re^3: Best way to check if something is a file handle?
by Athanasius (Chancellor) on Jul 09, 2012 at 10:18 UTC

    Not really surprising, since, according to perldoc,

    UNIVERSAL is the base class from which all blessed references inherit

    that is, the can method applies only to objects.

    Would something like this do?

    #! perl use strict; use warnings; my $in_file = 'temp1.txt'; # this must exist my $outfile = 'temp2.txt'; my $arrayref = []; open(my $in, '<', $in_file) or die "Cannot open file '$in_file' for r +eading: $!"; open(my $out, '>', $outfile) or die "Cannot open file '$outfile' for w +riting: $!"; can_write( $in_file, $in); can_write( $outfile, $out); can_write('$arrayref', $arrayref); close($in) or die "Cannot close file '$in_file': $!" +; close($out) or die "Cannot close file '$outfile': $!" +; sub can_write { my ($name, $fh) = @_; my $result = eval { no warnings; print $fh '' }; printf "$name %s write\n", ($result ? 'can' : 'cannot'); } __END__ temp1.txt cannot write temp2.txt can write $arrayref cannot write

    Update: The CPAN module FileHandle::Fmode by Sisyphus/syphilis may also be worth investigating, although it too appears not to work with IO::All objects.


    Athanasius <°(((><contra mundum

      The strange thing is that although $fh->can('close') doesn't return true, it also doesn't complain about there being no can method, whereas $fh->might('close') does complain about a missing might method. So it is, in some manner being treated as an object that kinda half implements the UNIVERSAL interface.

      Writing the empty string to a handle is quite a nice solution I suppose, but there may be some tied interfaces where printing even the empty string has side-effects. :-(

      And as it happens I'm actually more interested in reading than writing.

      perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'

        eval{} some innocuous operation such as $fh->format_name and check if an error has been generated. That takes 'duck typing' to its logical end; A filehandle can "format_name", so let's "format_name" and see if we get an error.

        However, you have to keep in mind that if $fh contains a glob that holds a string, that string will silently try to convert itself to a filehandle.

        For example: $something = 'STDOUT'; *someglob = $something; $fh = \*someglob; $fh->format_name; will be accepted just fine, because $fh contains a reference to a glob that holds the STDOUT filehandle, even though it was just a string only two operations ago. In fact the third layer of indirection isn't even needed; *someglob also contains a filehandle, of course. Perl would be equally happy with *someglob->format_name. And in fact, even $something->format_name is fine with Perl; as long as the string looks like a known filehandle, it's fine.

        On the other hand, $something = 'frobcinate'; $something->format_name; will throw an exception unless you've opened a filehandle named *frobcinate.

        This may be a terrible oversimplification that fails to work in some important cases. Certainly it would fail if $something were blessed into a class that is nothing like a filehandle except that it has a method named format_name.


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://980672]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (3)
As of 2018-01-19 18:23 GMT
Find Nodes?
    Voting Booth?
    How did you see in the new year?

    Results (222 votes). Check out past polls.