问题
The autodie documentation hints that it is possible to use it for other functions than those built-ins which it can handle by default, but there are no clear examples how to do that in it.
Specifically I would like to use it for the Imager module. A lot of the functions and methods of that can fail, and I would prefer if that wouldn't mean that my code will be littered with or die Imager|$image->errstr;
phrases all over.
Of course, if there's another way than using autodie to achieve that, I would be interested in that too.
回答1:
autodie only works with functions, not methods. This is because it's lexically scoped, and method lookup can't be lexically scoped. autodie::hints explains how to tell autodie about user-defined functions, but that won't do anything for methods.
I don't know of any way to get autodie-like behavior for methods, unless the module has that built in (e.g. DBI's RaiseError
).
You could have a subroutine to do the check, but it wouldn't save all that much code, since you'd still have to pass it the correct object or class to call errstr
on.
回答2:
See autodie::hints
回答3:
Here is an alternative technique that works with methods:
package SafeCall;
use Carp ();
sub AUTOLOAD {
my ($method) = our $AUTOLOAD =~ /([^:']+)$/; #'
unshift @_, my $obj = ${shift @_};
my $code = $obj->can($method)
or Carp::croak "no method '$method' on $obj";
&$code or Carp::croak $obj->can('errstr')
? $obj->errstr
: "calling $method on $obj failed"
}
And to use it:
package Image;
sub new {bless {here => 'ok', also => 'can be looked up'}};
sub fails {$_[0]{not_here}}
sub succeeds {$_[0]{here}}
sub lookup {$_[0]{$_[1]}}
sub errstr {'an error occurred'}
package main;
use 5.010; # for say()
my $safe = sub {bless \$_[0] => 'SafeCall'};
# storing the constructor in the scalar $safe allows $safe to be used
# as a method: $obj->$safe->method
my $img = Image->new;
say $img->$safe->succeeds; # prints 'ok'
say $safe->($img)->succeeds; # or call this way (also prints 'ok')
say $img->$safe->lookup('also'); # prints 'can be looked up'
say $img->$safe->fails; # dies with 'an error occurred at file.pl line ##'
来源:https://stackoverflow.com/questions/5337638/how-to-use-autodie-with-non-builtins