Как использовать AutoDie с не встроенными?

Документация autodie намекает на то, что его можно использовать для других функций, кроме тех встроенных, которые он может обрабатывать по умолчанию, но нет четких примеров, как это сделать в нем.

В частности, я хотел бы использовать его для модуля Imager. Многие функции и методы этого могут потерпеть неудачу, и я бы предпочел, чтобы это не означало, что мой код будет завален or die Imager|$image->errstr; фразы по всему.

Конечно, если есть другой способ, чем использовать autodie, я бы тоже заинтересовался этим.

3 ответа

Решение

autodie работает только с функциями, а не с методами. Это потому, что он имеет лексическую область видимости, а поиск метода не может быть ограничен лексической областью. autodie:: hints объясняет, как сообщить autodie о пользовательских функциях, но это ничего не даст для методов.

Я не знаю ни одного способа получить поведение, похожее на autodie, для методов, если только модуль не имеет встроенного (например, DBIRaiseError).

У вас может быть подпрограмма для проверки, но она не сэкономит столько кода, так как вам все равно придется передать ей правильный объект или класс для вызова errstr на.

Смотрите autodie::hints

Вот альтернативный метод, который работает с методами:

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 ##'
Другие вопросы по тегам