是否可以在运行时创建子例程签名?

Ste*_*ieD 5 raku

我在类中有一个方法:

    method options(*@opt) {
        if !@!valid-options {
            my $out = (cmd 'bin/md2html -h').out;
            my @matches = $out ~~ m:g/\s'--'(<-[\s]>+)/;
            for @matches -> $opt {
                push @!valid-options, $opt[0].Str;
            }
        }

        for @opt -> $opt {
            when !($opt (elem) @!valid-options) {
                warn "'$opt' is not a valid option";
            }
            push @!options, '--' ~ $opt;
        }
    }

Run Code Online (Sandbox Code Playgroud)

该方法检查选项以查看它们是否有效,如果有效,则将它们放入属性中。

我将参数传递到options方法中,如下所示:

$obj.options: <ftables ftasklists github>;

这有效。但这让我想知道是否可以将选项作为命名标志传递,如下所示:

$obj.options: :ftables, :ftasklists, :github

但由于我事先不知道命令的所有选项,因此我需要动态生成命名参数。这可能吗?我尝试过这个但没有运气:

# create a signature
my @params = Parameter.new(name => ':$option', type => Bool, :!default);
my $sig = Signature.new(:@params);

my &blah = -> $sig { say 'this works too' } ;
&blah(:option1);
Run Code Online (Sandbox Code Playgroud)

Eli*_*sen 6

目前,除了使用 之外,没有办法做到这一点EVAL

您可以将 slurpy 哈希添加到任何子签名以捕获所有意外的命名参数:

sub foo(*%_) { .say for %_.keys }
foo :bar, :baz;  # bar baz
Run Code Online (Sandbox Code Playgroud)

当 RakuAST 登陆时,在运行时创建您自己的签名可能会变得可能/更容易。