在子模块中重用父符号
Reuse parent symbols in child module
我正在寻求在子模块中重复使用与其父模块相同的 role/class 名称。你知道,就像一个专业。
目标是能够通过简单地将顶部的 use Dan
更改为 use Dan::Pandas
来为父系列和子系列变体重复使用相同的脚本代码。
我尽量坚持角色而不是 class 组合,以便可以将行为应用于其他对象,例如。 class GasBill does Series;
这是 MRE:
me@ubuntu:~/spike# tree
.
├── lib
│ ├── Dan
│ │ └── Pandas.rakumod
│ └── Dan.rakumod
└── spike.raku
Dan.rakumod:
1 unit module Dan;
2
3 role Series is export {
4 method no { "no" }
5 }
Pandas.rakumod:
1 unit module Dan::Pandas;
2
3 use Dan;
4
5 role Series does Dan::Series is export {
6 method yo { "yo" }
7 }
spike.raku:
1 use lib './lib';
2 use Dan::Pandas;
3
4 my $s = Series.new; #version 1
5 #my $s = Dan::Pandas::Series.new; #version 2 "fqm"
6
7 say $s.no, $s.yo, $s.^name;
我的版本 1 说:
No appropriate parametric role variant available for 'Dan::Series':
Ambiguous call to '(Dan::Series)'; these signatures all match:
(::$?CLASS ::::?CLASS Mu $)
(::$?CLASS ::::?CLASS Mu $)
in block <unit> at spike.raku line 4
我的版本 2 说:
Could not find symbol '&Series' in 'Dan::Pandas'
in block <unit> at spike.raku line 5
我相信 raku 确实有办法做到这一点,但如果我能解决这个问题该死!
如果我的理解正确,你不会 need/want 在最终模块中使用 non-specialized 角色(也就是说,你没有使用定义的 Series
in Dan.rakumod
in spike.raku
– 你只使用在 Pandas.rakumod
中定义的专门的 Series
)。对吗?
如果是这样,解决方案很简单:只是不要 export
来自 Dan.rakumod
的 Series
– 它仍然是 our
作用域(角色的默认值)所以您仍然可以在 Pandas.rakumod
中像现在一样使用它 (Dan::Series
)。但是,由于它没有导出,因此不会与 non-prefixed Series
.
产生名称冲突
TL;DR 您需要一个解决方案来避免两个角色具有相同的全名。
高尔夫
role R {}
role R {}
R.new
显示:
No appropriate parametric role variant available for 'R':
Ambiguous call to '(R)'; these signatures all match:
(::$?CLASS ::::?CLASS Mu $)
(::$?CLASS ::::?CLASS Mu $)
(有关错误消息的更多讨论,请参阅 Gut-referencing warning when composing stubbed role。)
一个解决方案
就Dan
.
Dan.rakumod
:
unit module Dan;
role Series is export { method no { "no" } }
spike.raku
:
use lib '.';
use Dan;
my $s = Series.new;
.say for $s.?no, $s.?yo, $s.^name;
运行 spike
显示:
no
Nil
Dan::Series
介绍Dan::Pandas
.
更改 Dan
以便变体模块可以 use
它 无需 它们 导入 Dan
的 未限定 Series
符号进入其词法范围。
(否则 Dan
的不合格 Series
符号最终会出现在它们的词法范围 以及 它们的 own 不合格的 Series
符号,你会得到“模糊调用”错误。)
Dan
:
unit module Dan;
role Series is export { method no { "no" } }
class Dan::Variant-Export-Dummy-Type is export(:Variant-Exports) {}
更改是最后一行,带有新导出标记的虚拟声明。 (以更简洁的方式介绍新标签留给读者作为练习。)
Dan::Pandas
:
unit module Dan::Pandas;
use Dan :Variant-Exports;
role Series does Dan::Series is export { method yo { "yo" } }
更改是使用带有 use Dan ...
语句的新 :Variant-Exports
标签。这会阻止 Dan
的 Series
角色以该非限定名称导入 Dan::Pandas
.
用户程序现在将作为 expected/wanted。
只需将spike.raku
中的use
语句改成:
use lib '.';
use Dan::Pandas;
my $s = Series.new;
.say for $s.?no, $s.?yo, $s.^name;
运行 只是用户程序的这个变化:
no
yo
Dan::Pandas::Series
请注意,使用这些模块的程序不需要了解 :Variant-Exports
标记。这只是 Dan
模块和 Dan::Pandas
等模块的内部细节,可以避免本答案开头显示的意外角色变体重复问题。
我的解决方案
听取@codesections [可以在没有 is export
的情况下使用 FQM] 和 @raiph [您可以使用例如限定导出的建议] is export(:ALL)
],那么 - 是的 - 有一种巧妙的方法可以做到这一点。
即。 https://docs.raku.org/language/modules#Exporting_and_selective_importing
事实证明,这是低级接触(只需更改两行),而且正如我最初希望的那样,这是 raku 设计师所预料到的。
这是我的 OP 调整后的代码...
Dan.rakumod:
1 unit module Dan;
2
3 role Series is export(:ALL) { #<== added the selective export
4 method no { "no" }
5 }
Pandas.rakumod(无变化):
1 unit module Dan::Pandas;
2
3 use Dan;
4
5 role Series does Dan::Series is export {
6 method yo { "yo" }
7 }
spike.raku:
1 use lib './lib';
2 #use Dan::Pandas; #\ either of these work
3 use Dan :ALL; #/ <== use :ALL to get 'Series'
4
5 my $s = Series.new;
6
7 say $s.no, $s.yo, $s.^name; #No such method 'yo' if Pandas not used
我正在寻求在子模块中重复使用与其父模块相同的 role/class 名称。你知道,就像一个专业。
目标是能够通过简单地将顶部的 use Dan
更改为 use Dan::Pandas
来为父系列和子系列变体重复使用相同的脚本代码。
我尽量坚持角色而不是 class 组合,以便可以将行为应用于其他对象,例如。 class GasBill does Series;
这是 MRE:
me@ubuntu:~/spike# tree
.
├── lib
│ ├── Dan
│ │ └── Pandas.rakumod
│ └── Dan.rakumod
└── spike.raku
Dan.rakumod:
1 unit module Dan;
2
3 role Series is export {
4 method no { "no" }
5 }
Pandas.rakumod:
1 unit module Dan::Pandas;
2
3 use Dan;
4
5 role Series does Dan::Series is export {
6 method yo { "yo" }
7 }
spike.raku:
1 use lib './lib';
2 use Dan::Pandas;
3
4 my $s = Series.new; #version 1
5 #my $s = Dan::Pandas::Series.new; #version 2 "fqm"
6
7 say $s.no, $s.yo, $s.^name;
我的版本 1 说:
No appropriate parametric role variant available for 'Dan::Series':
Ambiguous call to '(Dan::Series)'; these signatures all match:
(::$?CLASS ::::?CLASS Mu $)
(::$?CLASS ::::?CLASS Mu $)
in block <unit> at spike.raku line 4
我的版本 2 说:
Could not find symbol '&Series' in 'Dan::Pandas'
in block <unit> at spike.raku line 5
我相信 raku 确实有办法做到这一点,但如果我能解决这个问题该死!
如果我的理解正确,你不会 need/want 在最终模块中使用 non-specialized 角色(也就是说,你没有使用定义的 Series
in Dan.rakumod
in spike.raku
– 你只使用在 Pandas.rakumod
中定义的专门的 Series
)。对吗?
如果是这样,解决方案很简单:只是不要 export
来自 Dan.rakumod
的 Series
– 它仍然是 our
作用域(角色的默认值)所以您仍然可以在 Pandas.rakumod
中像现在一样使用它 (Dan::Series
)。但是,由于它没有导出,因此不会与 non-prefixed Series
.
TL;DR 您需要一个解决方案来避免两个角色具有相同的全名。
高尔夫
role R {}
role R {}
R.new
显示:
No appropriate parametric role variant available for 'R':
Ambiguous call to '(R)'; these signatures all match:
(::$?CLASS ::::?CLASS Mu $)
(::$?CLASS ::::?CLASS Mu $)
(有关错误消息的更多讨论,请参阅 Gut-referencing warning when composing stubbed role。)
一个解决方案
就
Dan
.Dan.rakumod
:unit module Dan; role Series is export { method no { "no" } }
spike.raku
:use lib '.'; use Dan; my $s = Series.new; .say for $s.?no, $s.?yo, $s.^name;
运行
spike
显示:no Nil Dan::Series
介绍
Dan::Pandas
.更改
Dan
以便变体模块可以use
它 无需 它们 导入Dan
的 未限定Series
符号进入其词法范围。(否则
Dan
的不合格Series
符号最终会出现在它们的词法范围 以及 它们的 own 不合格的Series
符号,你会得到“模糊调用”错误。)Dan
:unit module Dan; role Series is export { method no { "no" } } class Dan::Variant-Export-Dummy-Type is export(:Variant-Exports) {}
更改是最后一行,带有新导出标记的虚拟声明。 (以更简洁的方式介绍新标签留给读者作为练习。)
Dan::Pandas
:unit module Dan::Pandas; use Dan :Variant-Exports; role Series does Dan::Series is export { method yo { "yo" } }
更改是使用带有
use Dan ...
语句的新:Variant-Exports
标签。这会阻止Dan
的Series
角色以该非限定名称导入Dan::Pandas
.
用户程序现在将作为 expected/wanted。
只需将
spike.raku
中的use
语句改成:use lib '.'; use Dan::Pandas; my $s = Series.new; .say for $s.?no, $s.?yo, $s.^name;
运行 只是用户程序的这个变化:
no yo Dan::Pandas::Series
请注意,使用这些模块的程序不需要了解
:Variant-Exports
标记。这只是Dan
模块和Dan::Pandas
等模块的内部细节,可以避免本答案开头显示的意外角色变体重复问题。
我的解决方案
听取@codesections [可以在没有 is export
的情况下使用 FQM] 和 @raiph [您可以使用例如限定导出的建议] is export(:ALL)
],那么 - 是的 - 有一种巧妙的方法可以做到这一点。
即。 https://docs.raku.org/language/modules#Exporting_and_selective_importing
事实证明,这是低级接触(只需更改两行),而且正如我最初希望的那样,这是 raku 设计师所预料到的。
这是我的 OP 调整后的代码...
Dan.rakumod:
1 unit module Dan;
2
3 role Series is export(:ALL) { #<== added the selective export
4 method no { "no" }
5 }
Pandas.rakumod(无变化):
1 unit module Dan::Pandas;
2
3 use Dan;
4
5 role Series does Dan::Series is export {
6 method yo { "yo" }
7 }
spike.raku:
1 use lib './lib';
2 #use Dan::Pandas; #\ either of these work
3 use Dan :ALL; #/ <== use :ALL to get 'Series'
4
5 my $s = Series.new;
6
7 say $s.no, $s.yo, $s.^name; #No such method 'yo' if Pandas not used