如何捕获Raku方法名解析错误并抛出X::NYI异常?
解决方法:拦截
.&调用抛出X::NYI异常 首先得明确:你说的没错,.&是Raku编译器特殊处理的语法糖,没办法直接通过定义postfix:<.&>操作符来覆盖——这就是你最初代码失败的核心原因。不过你考虑的两种方向都有可行的实现方式,下面分别拆解:
1. 覆盖Mu的dispatch方法(全局生效)
这是最直接的方案,因为Mu是所有Raku类型的根类,它的dispatch方法负责处理所有方法调用的分发逻辑。.&本质上是间接方法调用,会触发带有特殊标记的$name参数,我们可以在dispatch里识别这个标记并抛出异常。
示例代码:
# 先定义X::NYI异常类(如果还没定义的话) class X::NYI is Exception { has $.feature; has $.did-you-mean; has $.workaround; method message() { "Feature $.feature is not yet implemented.\nDid you mean: $.did-you-mean?\nWorkaround: $.workaround" } } # 全局覆盖Mu的dispatch方法 augment class Mu { method dispatch($name, |args) { # .&调用会传入带&前缀的方法名,比如调用$obj.&foo时,$name是'&foo' if $name.starts-with('&') { die X::NYI.new( feature => $name.substr(1), did-you-mean => "a regular method call with `.foo` instead of `.&foo`", workaround => "Implement the method directly in the class, or use a standalone subroutine" ); } # 非.&调用,走正常的方法分发逻辑 callsame; } } # 测试一下 my $test-obj = class {}.new; $test-obj.&missing-method; # 这里会抛出X::NYI异常
2. 自定义元模型(针对特定类生效)
如果你不想全局拦截所有.&调用,只想针对某个类生效,那么修改Metamodel::ClassHOW的方法查找逻辑是更好的选择。元模型是Raku类的底层实现,我们可以通过自定义元类来拦截方法查找过程。
示例代码:
class X::NYI is Exception { has $.feature; has $.did-you-mean; has $.workaround; method message() { "Feature $.feature is not yet implemented.\nDid you mean: $.did-you-mean?\nWorkaround: $.workaround" } } # 自定义元类,继承自默认的ClassHOW class NYI::MetaClass is Metamodel::ClassHOW { method find_method($obj, $name) { # 同样识别.&带来的带&前缀的方法名 if $name.starts-with('&') { die X::NYI.new( feature => $name.substr(1), did-you-mean => "defining the method inside the class", workaround => "Add the method to your class definition, or use a regular sub" ); } # 正常查找方法 callsame; } } # 使用自定义元类创建目标类 class MyClass does NYI::MetaClass { # 这里可以定义类的正常方法 } # 测试 my $obj = MyClass.new; $obj.¬-here; # 抛出X::NYI异常
额外说明:你最初代码的报错原因
你之前写的my $let's-see = Nothing.newish;报错,是因为Nothing类里没有定义newish方法,而且默认继承的Any类也没有这个方法——这和.&的尝试完全无关,只是普通的方法缺失问题。如果要创建类的实例,应该用new方法:Nothing.new。
内容的提问来源于stack exchange,提问作者jjmerelo
相关产品推荐
相关产品推荐

