如何通过扩展正在使用的 class 来扩展模块?
How to extend a module by extending a class that it is using?
一些背景: 我想在 Perl 5 中扩展 JSON::Tiny
to allow for more relaxed parsing of lists. This is similar to the relaxed
flag for JSON::XS
。具体来说,我希望可以选择在列表末尾放置一个逗号。例如,{ "a" : 1, "b" : 2, }
。注意 2
后的逗号,这是正常的 JSON 语法规范(或 JSON::Tiny
)所不允许的。
通过检查 source code it seems this could be as simple as extending one of the modules, 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
}
请注意,对 JSON::Tiny::Grammar
的唯一修改是
为 pairlist
和 arraylist
规则引入 %%
运算符而不是 %
运算符。
这样的扩展将允许代码
重用。 (复制 JSON::Tiny
中的所有代码的替代方案是最后的选择。)
问题:现在的问题是我应该如何在不修改或复制JSON::Tiny
代码的情况下创建我的扩展(称为JSON::Relaxed
)?这是我要编写的模块的草图:
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
实现上面评论中的 a) 和 b) 的最佳方法是什么?
您可以像这样分别引入语法和动作:
use JSON::Tiny::Grammar;
use JSON::Tiny::Actions;
然后像问题中一样推导出自己的语法。
使用生成的语法和现有的操作 class,您将得到
JSON::Relaxed::Grammar.parse($input, :actions(JSON::Tiny::Actions)).ast
请注意,在 META6.json you can find the provides section 中可以准确地告诉您可以做什么 use
。
由于您想从 JSON::Tiny
中获取原始 to-json
,因此您必须导出转发到原始文件的 to-json
。这是执行此操作的代码:
sub to-json(|c) is export {
use JSON::Tiny;
to-json(|c);
}
这将使来自 JSON::Tiny
的符号仅在您的 to-json
函数的词法范围内可用,它将只接受其所有参数并使用它们调用原始 to-json
函数.
一些背景: 我想在 Perl 5 中扩展 JSON::Tiny
to allow for more relaxed parsing of lists. This is similar to the relaxed
flag for JSON::XS
。具体来说,我希望可以选择在列表末尾放置一个逗号。例如,{ "a" : 1, "b" : 2, }
。注意 2
后的逗号,这是正常的 JSON 语法规范(或 JSON::Tiny
)所不允许的。
通过检查 source code it seems this could be as simple as extending one of the modules, 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
}
请注意,对 JSON::Tiny::Grammar
的唯一修改是
为 pairlist
和 arraylist
规则引入 %%
运算符而不是 %
运算符。
这样的扩展将允许代码
重用。 (复制 JSON::Tiny
中的所有代码的替代方案是最后的选择。)
问题:现在的问题是我应该如何在不修改或复制JSON::Tiny
代码的情况下创建我的扩展(称为JSON::Relaxed
)?这是我要编写的模块的草图:
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
实现上面评论中的 a) 和 b) 的最佳方法是什么?
您可以像这样分别引入语法和动作:
use JSON::Tiny::Grammar;
use JSON::Tiny::Actions;
然后像问题中一样推导出自己的语法。
使用生成的语法和现有的操作 class,您将得到
JSON::Relaxed::Grammar.parse($input, :actions(JSON::Tiny::Actions)).ast
请注意,在 META6.json you can find the provides section 中可以准确地告诉您可以做什么 use
。
由于您想从 JSON::Tiny
中获取原始 to-json
,因此您必须导出转发到原始文件的 to-json
。这是执行此操作的代码:
sub to-json(|c) is export {
use JSON::Tiny;
to-json(|c);
}
这将使来自 JSON::Tiny
的符号仅在您的 to-json
函数的词法范围内可用,它将只接受其所有参数并使用它们调用原始 to-json
函数.