如何将 autodie 与非内置函数一起使用?

发布于 2024-10-23 11:42:32 字数 232 浏览 1 评论 0原文

autodie 文档暗示,除了默认情况下可以处理的内置函数之外,还可以将它用于其他功能,但没有明确的示例如何在其中执行此操作。

具体来说,我想将它用于成像器模块。其中的许多函数和方法都可能会失败,我希望这不会意味着我的代码将到处都是 或 die Imager|$image->errstr; 短语。

当然,如果除了使用 autodie 之外还有其他方法来实现这一点,我也会对此感兴趣。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

萌面超妹 2024-10-30 11:42:32

autodie 仅适用于函数,不适用于方法。这是因为它是词法作用域的,而方法查找不能是词法作用域的。 autodie::hints 解释了如何告诉 autodie 有关用户定义函数的信息,但是不会对方法做任何事情。

我不知道有什么方法可以让方法获得类似自动死亡的行为,除非模块内置了该行为(例如 DBIRaiseError)。

您可以使用一个子例程来执行检查,但它不会保存那么多代码,因为您仍然必须向其传递正确的对象或类来调用 errstr

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.

唱一曲作罢 2024-10-30 11:42:32

这是一种与方法一起使用的替代技术:

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 ##'

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 ##'
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文