为什么Try :: Tiny的“try {}”与try块中创建的对象的“eval {}”不同?

时间:2017-01-28 02:01:20

标签: perl try-catch eval gtk3 perl-critic

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

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,但似乎或多或少来自Exception handling examples in the POD of Glib::Object::Introspection

但是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满意?

2 个答案:

答案 0 :(得分:3)

批评的重点是避免检查$@,因为它可能已被破坏。但是,在完成所有更改后,您仍在检查$@

更糟糕的是,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;

没有Try :: Tiny:

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;

答案 1 :(得分:0)

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

对不起噪音。