捕捉并抛出自定义异常

时间:2019-09-21 14:47:16

标签: raku

是否应该在“抛出”之后严格调用“ CATCH”?

示例1:

const returnVal = [["Christ", "Evans", "Male", 1982], ["Robert", "Downey", "Male"]].map(person => {
return {
  firstName: person[0],
  lastName: person[1],
  gender: person[2],
  age: person[3] === undefined ? "Invalid Birth Year": person[3]
};

错误:

  

找不到方法“接收器”:没有方法缓存,也没有。^ find_method   在/tmp/739536251/main.pl6第11行处阻止

示例2:

say 'Hello World!';

class E is Exception { method message() { "Just stop already!" } }

CATCH {
    when E {
            .resume;
    }
}

E.new.throw;

没有错误

2 个答案:

答案 0 :(得分:4)

CATCH必须在同一块中。

第一个示例中的问题是没有E,而是引发了另一个异常。试试

class E is Exception { method message() { "Just stop already!" } };

CATCH {
    when E {
        .resume;
    }
    default { say .perl }
}

E.new.throw;

您可以更改when

class E is Exception { method message() { "Just stop already!" } };

CATCH {
    when E {
        say .message;
    }
}

E.new.throw;

或类E的定义,例如

class E is Exception { 
    has $.resume; 
    method message() { "Just stop already!" } 
};

CATCH {
    when E {
        say .resume;
    }
}

E.new(resume => 'stop here').throw;

答案 1 :(得分:4)

an already filed .resume bug


该错误消息并不是P6产生的最出色的消息,但从技术上来说并不是LTA,因为它是描述性的,并且与错误相关(由错误引起)。


  

捕获并引发自定义异常

我认为这只是一个.resume错误,而不是关于自定义异常的问题。

  

是否应该在“抛出”之后严格调用“ CATCH”?

不,那不是问题。 (也就是说,将其放在.throw之后只是为了避免此错误;我稍后会再讨论。)


在蓬勃发展的代码中,您引发异常,然后.resume对此作出响应。根据文档.resume

  

.throw离开的地方恢复控制流

在这种情况下,这意味着箭头所指的位置:

E.new.throw ;
           ?

现在,考虑以下程序:

42;

如果您运行该程序,则会看到:

Useless use of constant integer 42 in sink context (line 1)

这是因为P6在决定语句末尾的操作时会应用"sink context"规则。应用接收器上下文需要对语句产生的值调用.sink。对于42.sink方法会生成“无用”警告。

但是.resume引发的异常的值是什么?

class E is Exception {}
CATCH { when E { .resume } }
say E.new.throw.^name; # BOOTException
E.new.throw.sink;      # Cannot find method 'sink': no method cache and no .^find_method

事实证明,它是一个BOOTException对象,它不是高级P6对象,而是一个低级VM对象,它没有.sink方法(也阻碍了P6的后备查找方法的方法,因此出现“我尝试了一切”错误消息。


那么为什么将CATCH块放在之后会有所不同?

似乎错误仅在throw语句为 last 语句时发生。正常工作,只显示42

class E is Exception {}
CATCH { when E { .resume } }
E.new.throw;
say 42;

您大概知道,P6特别对待块的最后一条语句。也许这个错误与此有关。