Отношение между Failure
и Exception
заключается в том, что a Failure
имеет Exception
- то есть оно содержит объект исключения как часть своего состояния. Что-то вроде этого:
class Failure {
has Exception $.exception;
# ...
}
Когда Failure
«взрывается», он делает это, бросая то, Exception
что находится внутри него. Таким образом, то, что достигает CATCH
блока, является Exception
объектом, и нет обратной ссылки на вложение Failure
. (На самом деле, данный Exception
объект в принципе может удерживаться многими Failure
с.)
Следовательно, нет прямого способа обнаружить это. С точки зрения дизайна, вы, вероятно, не должны, и должны найти другой способ решения вашей проблемы. A Failure
- это просто способ отложить выдачу исключения и позволить ему рассматриваться как значение; не предполагается, что природа основной проблемы меняется, потому что она передается как значение, а не как непосредственная передача потока управления. К сожалению, первоначальная цель не была указана в вопросе; вам может быть полезно взглянуть на исключения управления, но в противном случае, возможно, опубликуйте другой вопрос об основной проблеме, которую вы пытаетесь решить. Там, наверное, лучший способ.
Для полноты картины отмечу , что есть косвенные способы , которые можно обнаружить , что Exception
был брошенной Failure
. Например, если вы получили .backtrace
объект исключения и посмотрите на пакет верхнего фрейма, можно определить, что он исходит из Failure
:
sub foo() { fail X::AdHoc.new(message => "foo") }
try {
foo();
CATCH {
note do { no fatal; .backtrace[0].code.package ~~ Failure };
.resume
}
}
Однако это сильно зависит от деталей реализации, которые могут легко измениться, поэтому я бы не стал на это полагаться.
try
Блок подразумеваетuse fatal
прагму, что означает, что любойFailure
возвращенный вызов, сделанный в блоке, немедленно преобразуется в исключение. Просто не используйтеtry
; АCATCH
может пойти в любой блок в Раку (так что просто сделайте это на уровнеsub
). В качестве альтернативы, напишитеno fatal
в верхней части вашегоtry
блока.True
на версии Rakudo, которую я имею на месте. Если это не по вашему, это просто доказывает, насколько хрупко это делать.Просто удалите
try
обертку:Вы использовали
try
. Atry
делает несколько вещей, но здесь уместно то, что он говорит Raku немедленно повышать любыеFailure
s в своей области до исключений - это то, что вы говорите, что не хотите. Поэтому самое простое решение - просто перестать это делать.Этот ответ лишь многословно повторяет часть объяснения jnthn (см., В частности, комментарии, которые он написал ниже своего ответа). Но я не был уверен, что все читатели заметят / поймут этот аспект, и не думал, что один или два комментария к ответу jnthn помогут, следовательно, этот ответ.
Я написал это как ответ сообщества, чтобы гарантировать, что я не получу никакой пользы от голосов, потому что это, очевидно, не гарантирует этого. Если он получит достаточно голосов, мы просто удалим его.
источник