如何创建和导出动态运算符
how to create and export dynamic operators
我有一些 类(并且还需要更多)看起来像这样:
use Unit;
class Unit::Units::Ampere is Unit
{
method TWEAK { with self {
.si = True;
# m· kg· s· A ·K· mol· cd
.si-signature = [ 0, 0, 0, 1, 0, 0, 0 ];
.singular-name = "ampere";
.plural-name = "ampere";
.symbol = "A";
}}
sub postfix:<A> ($value) returns Unit::Units::Ampere is looser(&prefix:<->) is export(:short) {
return Unit::Units::Ampere.new( :$value );
};
sub postfix:<ampere> ($value) returns Unit::Units::Ampere is looser(&prefix:<->) is export(:long) {
$value\A;
};
}
我希望能够在运行时动态构建和导出自定义运算符。我知道如何使用 EXPORT,但如何即时创建后缀运算符?
对于第一个问题,您可以通过从另一个返回子来创建动态子。要仅接受 Ampere
参数(其中以编程方式选择 "Ampere"),请在函数签名中使用 type capture:
sub make-combiner(Any:U ::Type $, &combine-logic) {
return sub (Type $a, Type $b) {
return combine-logic($a, $b);
}
}
my &int-adder = make-combiner Int, {$^a + $^b};
say int-adder(1, 2);
my &list-adder = make-combiner List, {(|$^a, |$^b)};
say list-adder(<a b>, <c d>);
say list-adder(1, <c d>); # Constraint type check fails
请注意,当我定义内部 sub
时,我必须在 sub
关键字之后放置一个 space,以免编译器认为我正在调用一个名为 "sub"。 (请参阅我的答案末尾了解另一种方法。)
现在,进入困难的部分:如何导出其中一个生成的函数? is export
真正作用的文档在这里:https://docs.perl6.org/language/modules.html#is_export
在页面的一半位置,他们有一个向符号 table 添加函数的示例,而无法在编译时编写 is export
。为了使上述工作正常,它需要在一个单独的文件中。要查看以编程方式确定的名称和以编程方式确定的逻辑的示例,请创建以下 MyModule.pm6:
unit module MyModule;
sub make-combiner(Any:U ::Type $, &combine-logic) {
anon sub combiner(Type $a, Type $b) {
return combine-logic($a, $b);
}
}
my Str $name = 'int';
my $type = Int;
my package EXPORT::DEFAULT {
OUR::{"&{$name}-eater"} := make-combiner $type, {$^a + $^b};
}
调用 Perl 6:
perl6 -I. -MMyModule -e "say int-eater(4, 3);"
正如所希望的那样,输出是 7。请注意,在这个版本中,我使用了 anon sub
,它允许您命名生成的函数 "anonymous"。我知道这主要用于生成更好的堆栈跟踪。
综上所述,我在动态设置后缀运算符的优先级时遇到了问题。我觉得你需要修改operator的Precedence
角色,或者自己创建,而不是让编译器帮你创建。这没有记录。
我基本上做了 this:
sub EXPORT
{
return %(
"postfix:<A>" => sub is looser(&prefix:<->) {
#do something
}
);
}
简单得令人不安。
我有一些 类(并且还需要更多)看起来像这样:
use Unit;
class Unit::Units::Ampere is Unit
{
method TWEAK { with self {
.si = True;
# m· kg· s· A ·K· mol· cd
.si-signature = [ 0, 0, 0, 1, 0, 0, 0 ];
.singular-name = "ampere";
.plural-name = "ampere";
.symbol = "A";
}}
sub postfix:<A> ($value) returns Unit::Units::Ampere is looser(&prefix:<->) is export(:short) {
return Unit::Units::Ampere.new( :$value );
};
sub postfix:<ampere> ($value) returns Unit::Units::Ampere is looser(&prefix:<->) is export(:long) {
$value\A;
};
}
我希望能够在运行时动态构建和导出自定义运算符。我知道如何使用 EXPORT,但如何即时创建后缀运算符?
对于第一个问题,您可以通过从另一个返回子来创建动态子。要仅接受 Ampere
参数(其中以编程方式选择 "Ampere"),请在函数签名中使用 type capture:
sub make-combiner(Any:U ::Type $, &combine-logic) {
return sub (Type $a, Type $b) {
return combine-logic($a, $b);
}
}
my &int-adder = make-combiner Int, {$^a + $^b};
say int-adder(1, 2);
my &list-adder = make-combiner List, {(|$^a, |$^b)};
say list-adder(<a b>, <c d>);
say list-adder(1, <c d>); # Constraint type check fails
请注意,当我定义内部 sub
时,我必须在 sub
关键字之后放置一个 space,以免编译器认为我正在调用一个名为 "sub"。 (请参阅我的答案末尾了解另一种方法。)
现在,进入困难的部分:如何导出其中一个生成的函数? is export
真正作用的文档在这里:https://docs.perl6.org/language/modules.html#is_export
在页面的一半位置,他们有一个向符号 table 添加函数的示例,而无法在编译时编写 is export
。为了使上述工作正常,它需要在一个单独的文件中。要查看以编程方式确定的名称和以编程方式确定的逻辑的示例,请创建以下 MyModule.pm6:
unit module MyModule;
sub make-combiner(Any:U ::Type $, &combine-logic) {
anon sub combiner(Type $a, Type $b) {
return combine-logic($a, $b);
}
}
my Str $name = 'int';
my $type = Int;
my package EXPORT::DEFAULT {
OUR::{"&{$name}-eater"} := make-combiner $type, {$^a + $^b};
}
调用 Perl 6:
perl6 -I. -MMyModule -e "say int-eater(4, 3);"
正如所希望的那样,输出是 7。请注意,在这个版本中,我使用了 anon sub
,它允许您命名生成的函数 "anonymous"。我知道这主要用于生成更好的堆栈跟踪。
综上所述,我在动态设置后缀运算符的优先级时遇到了问题。我觉得你需要修改operator的Precedence
角色,或者自己创建,而不是让编译器帮你创建。这没有记录。
我基本上做了 this:
sub EXPORT
{
return %(
"postfix:<A>" => sub is looser(&prefix:<->) {
#do something
}
);
}
简单得令人不安。