in reply to Accepting either a filename or a handle
There are several possible approaches to this. One is to assume that anything passed is either a simple string or an appropriate handle, and just choose between the two:
if (ref $param) { # it isn't a simple string, assume it is a filehandle $fh = $param; } else { open $fh, "<", $param or die "$param: $!"; }
A second approach is to require one of a set of specific types, but this disallows inherited types:
my $type = ref $param; if (!$type) { # it's a simple scalar } elsif ($type eq 'GLOB') { # an unblessed GLOB ref } elsif ($type eq 'IO::Handle') { # it's a non-overloaded IO::Handle } else { ... }
(When using this approach or some of the others, it is also worth being aware of Scalar::Util which has methods blessed() and reftype() for finer distinctions than ref() offers.)
A third approach is to look for inherited types using isa():
if (!ref $param) { # scalar } elsif (ref($param) eq 'GLOB') { # GLOB } elsif ($param->isa('IO::Handle')) { # is, or inherits from, IO::Handle } else { ... }
Yet another possibility is to test for the features you need with can(); say the only thing you need to be able to do with it is readline you could say:
if (!ref $param) { # scalar } elsif ($param->can('readline')) { # who knows what it is? But it supports a readline method ... } else { ... }
The various approaches all have different benefits and drawbacks, and which suits you best will depend on the specifics of your application. In general, though, I prefer the first: check as little as possible early on, and let the later code fail with a message such as:
Can't locate method 'readline' via package 'IO::StrangeHandle'
In particular, this approach is the least likely to stop someone using your routine with some object that they know should work, but due to some strangeness in how it describes itself might fail to match one of the other checks.
Hugo
|
|---|