How can I use EVAL to pass arguments to subroutines?

Viewed 466

I'm experimenting with Raku and trying to figure out how I might write a program with subcommands. When I run, ./this_program blah:

#! /usr/bin/env raku
use v6;

sub MAIN($cmd, *@subcommands) {
    $cmd.EVAL;
}

sub blah() { say 'running blah'; };

I get running blah output.

But this is as far as I got. I've tried various things, but I see no obvious way to pass @subscommands down to the blah function.

I'm not even sure if EVAL is the way to go either, but I couldn't find any other solution.

2 Answers

I think EVAL isn't strictly necessary here. You can go for indirect lookup, i.e.,

&::($cmd)(@sub-commands);

At the point &::($cmd), the function &blah is looked up from the string $cmd and is ready to use; we then call it with @sub-commands.

Then we have

sub MAIN($cmd, *@sub-commands) {
    &::($cmd)(@sub-commands);
}

sub blah(*@args) {
    say "running `blah` with `{@args}`";
}

and running as

$ raku ./program blah this and that

gives

running `blah` with `this and that`

Making MAIN a multi could also be a solution:

multi sub MAIN('blah', *@rest) {
    say "running blah with: @rest[]";
}
multi sub MAIN('frobnicate', $this) {
    say "frobnicating $this";
}
Related