为什么 Try::Tiny 的"try {}"看起来与在 try 块中创建的对象"eval {}"不同?



>我在系统托盘小程序中有以下初始化代码:

use Gtk3 -init;
use Glib::Object::Introspection;
eval {
    Glib::Object::Introspection->setup(
        basename => 'Notify',
        version => '0.7',
        package => "MyProgram::Notify",
        );
};
if ($@) {
    say "no notify because setup failed: $@";
    $use_notify = 0;
} else {
    MyProgram::Notify->init();
}

该代码基于 fdpowermon,但似乎或多或少来自 Glib::Object::Introspection 的 POD 中的异常处理示例。

但是perlcritic(在第3级)对此进行了争论:

Return value of eval not tested at line …

所以我试图用 Try::Tiny 重写它:

use Gtk3 -init;
use Glib::Object::Introspection;
use Try::Tiny;
try {
    Glib::Object::Introspection->setup(
        basename => 'Notify',
        version => '0.7',
        package => "MyProgram::Notify",
        );
} catch {
    say "no notify because setup failed: $@";
    $use_notify = 0;
} finally {
    if (!$@) {
        MyProgram::Notify->init();
    }
}

但随后 perl 认为:

Can't locate object method "new" via package MyProgram::Notify::Notification

虽然我确实看到特别是finally块并不是一个真正的改进,但我不明白为什么使用 Try::Tiny 对 Glib::Object::Introspection 创建的包有如此大的影响。

或者有没有比 Try::Tiny 更好的方法让这段代码更优雅、更易读,同时让perlcritic满意?

批评的重点在于避免检查$@,因为它可能会被破坏。然而,在您进行所有更改之后,您仍在检查$@

更糟糕的是,Try::Tiny将错误放在$_中,而不是$@中,并且只放在catch块中。

我认为正在发生的事情是,由于上述错误,MyProgram::Notify->init()在不应该调用的时候被调用。

修复:

my $use_notify = 1;
try {
    Glib::Object::Introspection->setup(
        basename => 'Notify',
        version => '0.7',
        package => "MyProgram::Notify",
    );
    MyProgram::Notify->init();
} catch {
    say "no notify because setup failed: $_";
    $use_notify = 0;
}

my $use_notify = 1;
try {
    Glib::Object::Introspection->setup(
        basename => 'Notify',
        version => '0.7',
        package => "MyProgram::Notify",
    );
} catch {
    say "no notify because setup failed: $_";
    $use_notify = 0;
}
MyProgram::Notify->init() if $use_notify;

无需尝试::微小:

my $use_notify = 1;
if (!eval {
    Glib::Object::Introspection->setup(
        basename => 'Notify',
        version => '0.7',
        package => "MyProgram::Notify",
    );
    MyProgram::Notify->init();
    1;  # No exception
}) {
    say "no notify because setup failed: " . ( $@ // "Unknown error" );
    $use_notify = 0;
}

my $use_notify = 1;
if (!eval {
    Glib::Object::Introspection->setup(
        basename => 'Notify',
        version => '0.7',
        package => "MyProgram::Notify",
    );
    1;  # No exception
}) {
    say "no notify because setup failed: " . ( $@ // "Unknown error" );
    $use_notify = 0;
}
MyProgram::Notify->init() if $use_notify;

实际上,我的问题的答案与此基本相同:catch(或者更确切地说是finally)块后面缺少分号。

对不起,噪音。

相关内容

  • 没有找到相关文章

最新更新