主子程序

标签 main raku subroutine

设想

假设您有一个模块 X用户可以通过命令行界面使用其功能。这样的模块本身并没有多大作用,但它允许其他人创建类似插件的模块,他们可以连接到模块 X .理想情况下,插件可以通过 X 使用。的 CLI。

因此我的问题是:

您需要做什么才能连接任何功能
一个插件可能会提供给 X的命令行界面?


这意味着插件需要提供一些结构来描述命令、需要调用的内容以及插件的使用信息。因此,当您运行 X的 CLI,插件的命令和帮助消息显示在常规 X的 CLI 的帮助消息。

例子
main.p6 :

use Hello;
use Print;

multi MAIN('goodbye') {
    put 'goodbye'
}
lib/Hello.pm6 :
unit module Hello;

our %command =  %(
    command => 'hello',
    routine => sub { return "Hello" },
    help    => 'print hello.'
);
lib/Print.pm6 :
unit module Print;

our %command =  %(
    command => 'print',
    routine => sub { .print for 1..10 },
    help    => 'print numbers 1 through 10.'
);

程序main.p6是此场景的简化版本。我想整合Hello.pm6 提供的信息和 Print.pm6通过
他们各自的%command变量成两个新的MAIN main.p6 中的潜艇.

这可能吗?如果是这样,我将如何实现它?

最佳答案

这看起来有点特定于 StackOverflow 问题,但无论如何我都会尝试一下。这里有几个问题。第一个是这样注册命令,以便 MAIN可以发出消息说“这样做”,第二是实际执行命令。如果两者都可以在编译时知道,这可能是固定的。但是让我们看看实际的代码会如何运行。我只做第一部分,剩下的留作练习。

第一件事是%command需要以某种方式导出。你不能像现在这样去做。首先,因为它没有明确导出;如果是这样,您最终会在外部范围内得到几个具有相同名称的符号。所以我们需要把它改成一个类,这样实际的符号对这个类来说是词法的,并且不会污染外部范围。

unit class Hello;

has %.command =  %(
    command => 'hello',
    routine => sub { return "Hello" },
    help    => 'print hello.'
);

(同样适用于 Print )

只要我们有这个,剩下的就不是那么难了,只是我们必须使用自省(introspection)来知道实际存在什么,作为一个小技巧:
use Hello;
use Print;

my @packages=  MY::.keys.grep( /^^<upper> <lower>/ );
my @commands = do for @packages -> $p {
    my $foo = ::($p).new();
    $foo.command()<command>
};

multi MAIN( $command where * eq any(@commands) ) {
    say "We're doing $command";
}

我们检查符号表以查找以大写字母开头的包,然后是其他非大写字母。碰巧只有我们感兴趣的包,但是当然,如​​果您想将其用作插件机制,则应该使用它们独有的任何模式。
然后我们创建这些新包的实例,并调用命令自动生成的方法来获取命令的名称。这正是我们用来检查 MAIN 中的命令是否正确的方法。子程序,通过使用 where签名来检查我们正在使用的字符串是否实际上在已知命令列表中。

由于功能和其余的东西也可以从 @packages 获得。 ,实际调用它们(或提供附加信息或其他)作为练习。

更新:您可能想查看 this other StackOveflow answer作为模块中签名的替代机制。

关于主子程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57041053/

相关文章:

function - Flex&Bison : define main function in a separate file

perl - 获取当前进程的 perl 可执行文件的绝对路径

date - Dateish 字符串的问题

perl - 我如何检查子例程是否返回 *nothing*

c - 退出状态是可观察的行为吗?

c++ - 递归中的主要功能

java - "Could not find or load main class"是什么意思?

raku - 我在哪里可以找到 Raku 核心转储文件?

vba - 在子 VBA 中停用 msgbox

perl - 如何将可选参数传递给 Perl 函数?