Как использовать AutoDie с не встроенными?
Документация autodie намекает на то, что его можно использовать для других функций, кроме тех встроенных, которые он может обрабатывать по умолчанию, но нет четких примеров, как это сделать в нем.
В частности, я хотел бы использовать его для модуля Imager. Многие функции и методы этого могут потерпеть неудачу, и я бы предпочел, чтобы это не означало, что мой код будет завален or die Imager|$image->errstr;
фразы по всему.
Конечно, если есть другой способ, чем использовать autodie, я бы тоже заинтересовался этим.
3 ответа
autodie работает только с функциями, а не с методами. Это потому, что он имеет лексическую область видимости, а поиск метода не может быть ограничен лексической областью. autodie:: hints объясняет, как сообщить autodie о пользовательских функциях, но это ничего не даст для методов.
Я не знаю ни одного способа получить поведение, похожее на autodie, для методов, если только модуль не имеет встроенного (например, DBIRaiseError
).
У вас может быть подпрограмма для проверки, но она не сэкономит столько кода, так как вам все равно придется передать ей правильный объект или класс для вызова errstr
на.
Вот альтернативный метод, который работает с методами:
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"
}
И использовать это:
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 ##'