具有可变数量实参的脚本

Script with a variable number of Real arguments

我正在尝试编写要调用的 Raku 脚本,例如

script 1.2 1.117 -2 0.037

即,想法是创建一个 sub MAIN(@numbers) 并以某种方式将数组 @numbers 设为 Real(不是 Str,不是 IntStr)。这样做的一种方法是将每个元素(如果可能)转换为 for,但我确信有更优雅的解决方案。

我会让读者判断以下是技术上的骇人听闻的黑客攻击,还是看起来令人厌恶,或者两者兼而有之。但这是我在当前 Raku 语法中所知道的最接近的东西。

首先,您需要接受数量可变的参数。 (你甚至需要 你的 代码才能正常工作。我想你打错了。)

我不会使用 * 或类似的方法,而是使用 |。我们马上就会知道为什么。

sub MAIN( |numbers ) { ... }

接下来,我添加一个子签名。

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

这利用了:

  • 命名参数是可选的;

  • 根据绑定到签名左侧参数的参数建立默认值;

  • 隐藏这个诡计,这样使用消息不受影响,这样(我认为)用户不能使用--reals=...注入值或类似的。 (实际上,说我认为他们不能太过分了。我希望他们不能。)

这要么是一个非常糟糕的黑客攻击,要么就是纯粹的邪恶。不要在工作时这样做!

到目前为止的代码假定参数确实是 Reals。如果他们不是,事情就会出错。我们也需要处理它。

所以我们添加一个 subset 并将其添加到签名中:

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

在这里我们看到了我使用 | 而不是 * 的主要原因;这是在 slurpy 的左侧写类型的唯一方法,否则我将不得不内联 where 并且整个事情会比现在更加丑陋。

因此我们得到:

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

正在显示,您的原始命令行:

(Rat)
(Rat)
(Int)
(Rat)