Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to provide a non-slurpy array or named array from the command line?

First of all: raku (perl6) is amazing. And so is Cro. It only took a week-end to fall in love. However now I stumble over something that must be extremely simple.

If I use a slurpy parameter in a multiple dispatch MAIN this is recognized and works perfectly:

multi MAIN( 'config', 'add', *@hostnames ) {

However if I make this a non-slurpy array, this is either not recognized or I don't know how to provide it from the command line:

multi MAIN( 'config', 'add', @hostnames ) {

I would expect one of these invocations to work:

$ cli.raku config add www.example.com example.com
$ cli.raku config add www.example.com,example.com
$ cli.raku config add www.example.com, example.com

A similar construct is used in the Cro CLI however without example of how to call one of the commands with an array in the docs.

I also tried this with an array as named parameter:

my %*SUB-MAIN-OPTS = :named-anywhere;
multi MAIN( 'config', 'add', :@hostnames) {

Given the example in the raku docs I would expect this to work:

$ cli.raku config add --hostnames=www.example.com example.com

But it does not, nor variants with comma or space comma separation. In all cases I get the usage information.

like image 771
acw Avatar asked Jun 04 '20 22:06

acw


1 Answers

The arg parsing that is built into Raku corresponds to standard shell features/conventions. As JJ notes, there is no shell feature/convention for individual arrays. I presume this is why plain @foo (and %bar) is not defined to match anything as part of the built in CLI parsing features.


Your example would be covered by a slurpy, and you haven't said why you don't want to use a slurpy.

One guess is that it's because a slurpy would allow zero arguments. Here's an idiomatic way to fix that:

multi MAIN( 'config', 'add', *@hostnames where +*) {

You can read the +* as "one or more".

What's actually going on there is that I've written a where clause. This is a constraint that's imposed on a variable or parameter in addition to any other constraint such as a type. A where clause is an arbitrary condition that evaluates as True or False. The value that is about to be bound to the variable/parameter (if it passes the constraint condition) is implicitly "it" for the condition.

Whenever an expression contains one or more operator(s) combined with one or more *s as operand(s), Raku converts the expression into a function, where the *(s) are parameters of that function.

So +* is a tiny little one parameter function that just applies a prefix + to its one argument aka "it".

When you apply prefix + to an array, it returns the Int count of elements in that array. The value returned from the condition expression is evaluated as a Bool -- True or False. If it's 0 (i.e. no arguments were passed), the constraint condition returns False so the MAIN signature fails to bind and the usage message gets displayed.


If that's not it, perhaps it's because you can use only one array slurpy per command line, at the end.

Or just curiosity.


A named array works like this:

sub MAIN ( :@n ) {}

my shell prompt> cli-prog.raku -n=www.example.com -n=example.com

A search of SO for "[raku] getopt"


You can take over control of CLI parsing to get whatever result you want:

  • A Raku getopt implementation

  • SuperMAIN, a strict superset of the built in MAIN functionality.

  • "My experience building out a command line application in production" (video, slides)

like image 92
raiph Avatar answered Oct 13 '22 01:10

raiph