Raku中如何将类的运算符重载拆分到独立文件并随类导入可用
错误原因纠正
你遇到的'use lib' may not be pre-compiled错误并非循环依赖导致,根本原因是你将use lib语句写在了会被预编译的*.rakumod模块文件中,use lib仅允许放在直接执行的入口脚本(也就是你的script.raku)中,模块文件不需要也不能加这行。
解决方案
你可以通过调整模块加载顺序和导入逻辑实现仅导入main模块就能使用所有自定义运算符的需求,步骤如下:
- 移除所有
*.rakumod模块文件中的use lib "."语句,仅保留script.raku中的这一行即可。 - 若你使用的是自定义的全新运算符,给运算符模块中的重载例程添加
is export修饰;如果只是重载Raku已有的标准运算符(比如++、+),不需要额外加导出修饰,只要模块被加载,多分派候选就会自动生效。 - 在
main.rakumod的类定义完成后再导入运算符模块,避免循环依赖问题。
调整后的代码示例
prefix_ops.rakumod
use main; # 重载已有标准运算符不需要加is export multi prefix:<++>(A:D $obj) { ++$obj.x; $obj; }
infix_ops.rakumod(参考修改)
use main; multi infix:<+>(A:D $a, A:D $b) { A.new(x => $a.x + $b.x) }
main.rakumod
class A { has $.x is rw; } # 类定义完成后再导入运算符模块,此时A已完成注册,不会触发循环依赖 use prefix_ops; use infix_ops;
script.raku(无需修改)
use lib "."; use main; my $a = A.new(x => -1); ++$a; say $a.x; # 输出 0,运行正常
原理解释
Raku的模块加载顺序是线性的,当在main模块的类定义完成后再导入运算符模块,此时A类已经完成注册,运算符模块use main时不会找不到类定义,也就不会出现循环依赖报错。运算符模块被加载后,重载的多分派候选会自动加入全局分派表,use main的脚本就可以直接调用这些自定义运算符。
内容的提问来源于stack exchange,提问作者user15750474
相关产品推荐
相关产品推荐

