5

I've got a method in a class:

    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;
        }
    }

The method checks that the options to see if they are valid and, if they are, places them into an attribute.

I pass args into the options method like this, as words:

$obj.options: <ftables ftasklists github>;

This works. But it got me wondering if it was possible pass in the options as named flags like this:

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

But since I don't know all the command's options ahead of time, I'd need to generate the named arguments dynamically. Is this possible? I tried this but had no luck:

# 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);
StevieD
  • 6,925
  • 2
  • 25
  • 45

1 Answers1

6

Currently, there is no way to do that, short of using EVAL.

You can add a slurpy hash to any sub signature to catch all unexpected named arguments:

sub foo(*%_) { .say for %_.keys }
foo :bar, :baz;  # bar baz

Creating your own signatures at runtime may become possible / easier when the RakuAST has landed.

Elizabeth Mattijsen
  • 25,654
  • 3
  • 75
  • 105