Почему Try::Tiny "try {}" отличается от "eval {}" для объектов, созданных внутри блока try?
У меня есть следующий код инициализации в системном трее апплета:
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, но, похоже, более или менее взят из примеров обработки исключений в POD 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 ответа
Весь смысл критики состоит в том, чтобы избежать проверки $@
потому что это могло быть забито. Но после всех ваших изменений вы все еще проверяете $@
!
Хуже, попробуйте:: Tiny помещает ошибку в $_
, не в $@
и только в catch
блоки.
Я думаю, что происходит то, что MyProgram::Notify->init()
вызывается, когда не следует из-за вышеперечисленных ошибок.
Fix:
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;
Без попытки:: 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;
На самом деле ответ на мой вопрос в основном такой же: пропущенная точка с запятой за catch
(или скорее finally
) блок.
Извините за шум.