syntax - 内省(introspection)模块/类/等的替代语法

标签 syntax raku symbolic-references

出于工作目的,我正在将一个框架从 Perl5 重​​写为 Perl6。在某个地方,我需要通过执行 public sub 从其他模块/类收集信息。他们可能会提供;或者他们可能不会。所以,有必要找出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 类的符号名称。

  • 它的字符串名称。 'Int' 是 Int 类的字符串名称。

Vadim 很合理地希望找到一个能够同时解决这两个问题的解决方案。

在此答案的解决方案中,我通过随机选择一种参数并将其分配给 $pkg-arg 来模拟两种类型的参数:

my $pkg-arg = (Int, 'Int').pick;

现在我们需要正常化。如果我们有了一个象征性的名字,我们就可以开始了。但如果它是字符串名称,我们需要将其转换为符号名称。

Vadim 在其问题的评论中展示了几种实现此目的的方法。该解决方案使用第三个选项:

my \pkg-sym = $pkg-arg && ::($pkg-arg);

如果$pkg-arg是一个符号名称,那么它将是False。对于 False LHS,&& 会短路并返回其 LHS。如果 $pkg-arg 是字符串名称,则 && 将返回其 RHS,即 ::($pkg-arg)这是使用 $pkg-arg 作为字符串名称的符号查找。

结果是 pkg-sym 最终包含一个包符号名称(如果查找未能找到匹配的符号名称,则返回 Failure)。

剩下最后一行。它会在包 pkg-sym 中查找名为 $subname 的子包:

my \sub-ref = &pkg-sym::($subname);

需要 & 以确保将 RHS 视为引用而不是尝试调用例程。并且 pkg-sym 必须是无符号标识符,否则代码将无法工作。

在这三行代码的末尾sub-ref包含Failure或对所需子的引用。

关于syntax - 内省(introspection)模块/类/等的替代语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51957518/

相关文章:

regex - 结合状态和 token 抛出。为什么?

ruby - 神秘的 ruby : Vector Assignment Example

java - 用于普通方法调用的标签 - Java

raku - 角色访问可以包含角色属性吗?

perl - 如何基于字符串创建 Perl 变量名?

git - Git 符号引用的推荐用法是什么?

c - 使用宏 STATIC 的重要性

c++ - 动态分配函数指针数组时发出警告

perl - 如何从 perl6 中的数组或散列创建方法