内省的替代语法 modules/classes/etc
Alternate syntax on introspecting modules/classes/etc
出于工作目的,我正在重写一个从 Perl5 到 Perl6 的框架。在某些地方,我需要通过执行他们可能提供的 public sub
从其他 modules/classes 收集信息;或者他们可能不会。因此,有必要找出 sub
是否存在。当直接引用模块 (Foo::<&my-sub>
) 或通过字符串中的符号名称 (&::("Foo")::my-sub) 时,这不是什么大问题。但是为了简单起见,我想允许按原样传递模块名称(可以说 collector
是收集信息的方法):
self.collector( Foo );
其中 Foo
可能是以下内容:
module Foo {
use Bar;
use Baz;
our sub my-sub { Bar, 'Baz' }
}
这就是我在 Perl6 语法中遗漏了一些重要的东西,因为:
method collector ( $mod ) {
my $mod-name = $mod.WHO;
my @mods;
with &::($mod-name)::my-sub {
@mods.push: &$_();
}
}
目前是我执行任务的唯一方法。
虽然我还没有尝试类型捕获。我想应该会按预期工作。所以,问题更多是关于扩展我的语法知识。
在对他们问题的评论中与 Vadim 交流的最终解决方案。这可以说是疯狂的。他们认为它很美。我要和谁争辩? .oO(哈哈,呵呵,嘻嘻...)
my $pkg-arg = (Int, 'Int').pick;
my \pkg-sym = $pkg-arg && ::($pkg-arg);
my \sub-ref = &pkg-sym::($subname);
有两种明显有用的方法来引用包:
它的符号名称。 Int
是 Int 的符号名称 class.
它的字符串名称。 'Int'
是 Int 的字符串名称 class.
Vadim 很合理地希望两者都有解决方案。
在这个答案的解决方案中,我通过随机选择一种并将其分配给 $pkg-arg
:
来模拟两种类型的参数
my $pkg-arg = (Int, 'Int').pick;
现在我们需要标准化。如果我们有一个象征性的名字,我们就可以开始了。但是如果它是一个字符串名称,我们需要把它变成符号名称。
Vadim 在对他们问题的评论中展示了几种方法。此解决方案使用第三个选项:
my \pkg-sym = $pkg-arg && ::($pkg-arg);
如果 $pkg-arg
是一个符号名称,它将是 False
。对于 False
LHS,&&
短路,return 是其 LHS。如果 $pkg-arg
是一个字符串名称,那么 &&
将代替 return 它的 RHS,即 ::($pkg-arg)
这是一个使用 $pkg-arg
作为字符串名称的符号查找.
结果是 pkg-sym
最终包含一个包符号名称(如果查找未能找到匹配的符号名称,则为 Failure
)。
剩下最后一行。在包 pkg-sym
:
中寻找名为 $subname
的子程序
my \sub-ref = &pkg-sym::($subname);
需要 &
以确保 RHS 被视为参考而不是尝试调用例程。 pkg-sym
必须是无符号标识符,否则代码将无法工作。
在这三行代码的末尾 sub-ref
包含 Failure
或对所需子项的引用。
出于工作目的,我正在重写一个从 Perl5 到 Perl6 的框架。在某些地方,我需要通过执行他们可能提供的 public sub
从其他 modules/classes 收集信息;或者他们可能不会。因此,有必要找出 sub
是否存在。当直接引用模块 (Foo::<&my-sub>
) 或通过字符串中的符号名称 (&::("Foo")::my-sub) 时,这不是什么大问题。但是为了简单起见,我想允许按原样传递模块名称(可以说 collector
是收集信息的方法):
self.collector( Foo );
其中 Foo
可能是以下内容:
module Foo {
use Bar;
use Baz;
our sub my-sub { Bar, 'Baz' }
}
这就是我在 Perl6 语法中遗漏了一些重要的东西,因为:
method collector ( $mod ) {
my $mod-name = $mod.WHO;
my @mods;
with &::($mod-name)::my-sub {
@mods.push: &$_();
}
}
目前是我执行任务的唯一方法。
虽然我还没有尝试类型捕获。我想应该会按预期工作。所以,问题更多是关于扩展我的语法知识。
在对他们问题的评论中与 Vadim 交流的最终解决方案。这可以说是疯狂的。他们认为它很美。我要和谁争辩? .oO(哈哈,呵呵,嘻嘻...)
my $pkg-arg = (Int, 'Int').pick;
my \pkg-sym = $pkg-arg && ::($pkg-arg);
my \sub-ref = &pkg-sym::($subname);
有两种明显有用的方法来引用包:
它的符号名称。
Int
是 Int 的符号名称 class.它的字符串名称。
'Int'
是 Int 的字符串名称 class.
Vadim 很合理地希望两者都有解决方案。
在这个答案的解决方案中,我通过随机选择一种并将其分配给 $pkg-arg
:
my $pkg-arg = (Int, 'Int').pick;
现在我们需要标准化。如果我们有一个象征性的名字,我们就可以开始了。但是如果它是一个字符串名称,我们需要把它变成符号名称。
Vadim 在对他们问题的评论中展示了几种方法。此解决方案使用第三个选项:
my \pkg-sym = $pkg-arg && ::($pkg-arg);
如果 $pkg-arg
是一个符号名称,它将是 False
。对于 False
LHS,&&
短路,return 是其 LHS。如果 $pkg-arg
是一个字符串名称,那么 &&
将代替 return 它的 RHS,即 ::($pkg-arg)
这是一个使用 $pkg-arg
作为字符串名称的符号查找.
结果是 pkg-sym
最终包含一个包符号名称(如果查找未能找到匹配的符号名称,则为 Failure
)。
剩下最后一行。在包 pkg-sym
:
$subname
的子程序
my \sub-ref = &pkg-sym::($subname);
需要 &
以确保 RHS 被视为参考而不是尝试调用例程。 pkg-sym
必须是无符号标识符,否则代码将无法工作。
在这三行代码的末尾 sub-ref
包含 Failure
或对所需子项的引用。