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

大兔子大兔子 提交于 2020-06-27 07:16:32

问题


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.


回答1:


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)



来源:https://stackoverflow.com/questions/62205330/how-to-provide-a-non-slurpy-array-or-named-array-from-the-command-line

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!