如何通过扩展它正在使用的类来扩展模块?

Håk*_*and 4 inheritance grammar perl6 raku

一些背景:我想扩展JSON::Tiny以允许更轻松的列表解析.这类似于Perl 5中的relaxed标志JSON::XS.具体来说,我希望可以选择在列表末尾添加逗号.例如,{ "a" : 1, "b" : 2, }.注意之后的逗号2,正常的JSON语法规范(或JSON::Tiny)不允许这样做.

通过检查源代码,它似乎可以像扩展其中一个模块JSON :: Tiny :: Grammar一样简单,它JSON::Tiny在内部使用,然后覆盖其两个规则:

grammar JSON::Relaxed::Grammar is JSON::Tiny::Grammar {
    rule pairlist   { <pair> * %% \,            } # override this rule
    rule arraylist  {  <value> * %% [ \, ]        } #overide this rule
}
Run Code Online (Sandbox Code Playgroud)

请注意,唯一的修改JSON::Tiny::Grammar是引入%%运算符而不是%操作符pairlistarraylist规则.

这样的扩展将允许代码重用.(复制所有代码的替代方案JSON::Tiny是最后的选择.)

问题:现在的问题是如何在JSON::Relaxed不修改或复制代码的情况下创建扩展(调用 )JSON::Tiny?这是我想写的模块的草图:

unit module JSON::Relaxed;
use v6;

use JSON::Tiny; # <-- since it is a module, I cannot extend it like a class

# a) export all the stuff that JSON::Tiny exports to the caller
# b) Somehow make JSON::Tiny use JSON::Relaxed::Grammar instead of JSON::Tiny::Grammar
Run Code Online (Sandbox Code Playgroud)

在上面的评论中,实现a)和b)的最佳方法是什么?

tim*_*imo 5

你可以像这样单独引入语法和动作:

use JSON::Tiny::Grammar;
use JSON::Tiny::Actions;
Run Code Online (Sandbox Code Playgroud)

然后像问题一样派生出你自己的语法.

使用生成的语法和现有的Actions类,你最终会得到

JSON::Relaxed::Grammar.parse($input, :actions(JSON::Tiny::Actions)).ast
Run Code Online (Sandbox Code Playgroud)

请注意,在META6.json中,您可以找到提供部分,它可以准确地告诉您use.

既然你想利用原来to-jsonJSON::Tiny,你将不得不导出to-json转发到原来的.这是执行此操作的代码:

sub to-json(|c) is export {
    use JSON::Tiny;
    to-json(|c);
}
Run Code Online (Sandbox Code Playgroud)

这将使符号JSON::Tiny仅在to-json函数的词法范围内可用,它将获取其所有参数并to-json使用它们调用原始函数.