Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Script with a variable number of Real arguments

Tags:

raku

I'm trying to write a Raku script to be called e.g.

script 1.2 1.117 -2 0.037

I.e., the idea is to create a sub MAIN(@numbers) and somehow get the array @numbers as Real (not Str, not IntStr). A way to do so is to cast each element (if possible) in a for, but I'm sure there is a more elegant solution.

like image 702
vonbrand Avatar asked Apr 14 '20 23:04

vonbrand


People also ask

What does variable number of arguments mean in JavaScript?

Variable number of arguments means the function can accept any number of arguments. In JavaScript, there are two ways of writing a function that accepts any number of arguments: Using the arguments object. Using the rest parameter. How to use the arguments object to create a function that accepts any number of arguments?

How many arguments can be passed to a function?

There is no function parameter limit, so you can call a function and pass in any number of arguments, regardless of what the function declaration specifies. There are two ways that can make it possible to create a function with any number of arguments specified. Watch a video course JavaScript - The Complete Guide (Beginner + Advanced)

What is the difference between arguments and Rest parameters?

The arguments is an Array-like object accessible inside functions containing the values of the arguments passed to that function. The rest parameter syntax allows adding an indefinite number of arguments as an array.

What is the difference between a function parameter and argument?

The difference between parameters and arguments is - function parameters are the names listed in the function's definition, and function arguments are the real values passed to the function when invoking it. Here is an example of using rest arguments. Copied!


1 Answers

I'll let readers judge whether the following is a technically atrocious hack, or looks hideously repugnant, or both. But it's the closest thing I'm aware of in current Raku syntax.

First, you need to accept a variable number of arguments. (You need that for even your code to work at all. I presume you typo'd.)

Rather than use * or similar I'll use |. We'll see why in a mo.

sub MAIN( |numbers ) { ... }

Next, I add a sub-signature.

sub MAIN( |numbers ( *@, :@reals = numbers».Real )) { ... }

This takes advantage of:

  • Named parameters being optional; and

  • Establishing a default value based on arguments bound to parameters to the left in a signature; and

  • Hiding this chicanery so the usage message is not affected, and so that (I think) the user cannot inject a value using --reals=... or similar. (Actually, saying I think they can't is far too strong. I hope they can't.)

This is either a pretty terrible hack or just plain evil. Don't do this at home work!

The code so far presumes that the arguments are indeed Reals. If they're not, things go wrong. We need to deal with that too.

So we add a subset and add that to the signature:

subset Reals where *».Real».defined.all;
sub MAIN( Reals |numbers ( *@, :@reals = numbers».Real )) { ... }

Here we see the main reason I used | rather than *; it's the only way to write a type on the left of a slurpy, Without that I'd have to inline the where and the whole thing would be even more unspeakably ugly than it is.

Thus we end up with:

subset Reals where *».Real».defined.all;
sub MAIN( Reals |numbers ( *@, :@reals = numbers».Real )) { .WHAT.say for @reals }

displaying, for your original command line:

(Rat)
(Rat)
(Int)
(Rat)
like image 101
raiph Avatar answered Nov 05 '22 13:11

raiph