gpt4 book ai didi

main - 改变参数在传递给子 MAIN 之前的处理方式

转载 作者:行者123 更新时间:2023-12-03 15:48:24 27 4
gpt4 key购买 nike

鉴于 documentation以及对 earlier question 的评论,根据要求,我制作了一个最小的可重现示例,演示了这两个语句之间的区别:

my %*SUB-MAIN-OPTS = :named-anywhere;
PROCESS::<%SUB-MAIN-OPTS><named-anywhere> = True;

给定一个只有这个的脚本文件:
#!/usr/bin/env raku
use MyApp::Tools::CLI;

以及 MyApp/Tools 中名为 CLI.pm6 的模块文件:
#PROCESS::<%SUB-MAIN-OPTS><named-anywhere> = True;
my %*SUB-MAIN-OPTS = :named-anywhere;

proto MAIN(|) is export {*}

multi MAIN( 'add', :h( :$hostnames ) ) {
for @$hostnames -> $host {
say $host;
}
}

multi MAIN( 'remove', *@hostnames ) {
for @hostnames -> $host {
say $host;
}
}

从命令行进行的以下调用不会产生可识别的子例程,但会显示用法:
mre.raku add -h=localhost -h=test1

切换 my %*SUB-MAIN-OPTS = :named-anywhere;对于 PROCESS::<%SUB-MAIN-OPTS><named-anywhere> = True;如预期的那样,将使用提供的两个主机名打印两行。

但是,如果这是在一个文件中完成的,如下所示,两者的工作方式相同:
#!/usr/bin/env raku

#PROCESS::<%SUB-MAIN-OPTS><named-anywhere> = True;
my %*SUB-MAIN-OPTS = :named-anywhere;

proto MAIN(|) is export {*}

multi MAIN( 'add', :h( :$hostnames )) {
for @$hostnames -> $host {
say $host;
}
}

multi MAIN( 'remove', *@hostnames ) {
for @hostnames -> $host {
say $host;
}
}

我觉得这很难理解。
重现此内容时,请注意必须如何调用每个命令。
mre.raku remove localhost test1
mre.raku add -h=localhost -h=test1

因此,当在带有 my %*SUB-MAIN-OPTS = :named-anywhere; 的单独文件中使用命名数组引用时,将无法识别它。 .而 PROCESS::<%SUB-MAIN-OPTS><named-anywhere> = True;总是有效。对于 slurpy 数组,两者在两种情况下的工作方式相同。

最佳答案

问题是它在脚本和模块中不是同一个变量。

当然他们有相同的名字,但这并不意味着什么。

my \A = anon class Foo {}
my \B = anon class Foo {}

A ~~ B; # False
B ~~ A; # False
A === B; # False

这两个类具有相同的名称,但是是独立的实体。

如果您查看其他内置动态变量的代码,您会看到如下内容:

Rakudo::Internals.REGISTER-DYNAMIC: '$*EXECUTABLE-NAME', {
PROCESS::<$EXECUTABLE-NAME> := $*EXECUTABLE.basename;
}

这可以确保将变量安装到正确的位置,以便它适用于每个编译单元。

如果您寻找 %*SUB-MAIN-OPTS ,你唯一能找到的就是这个 line :

    my %sub-main-opts   := %*SUB-MAIN-OPTS // {};

这会在主编译单元中查找变量。如果没有找到它,它会创建并使用一个空的哈希。

因此,当您尝试在主编译单元以外的范围内执行此操作时,它不在该行可以找到的位置。

要测试添加是否可以解决问题,您可以将其添加到主编译单元的顶部。 (加载模块的脚本。)

BEGIN Rakudo::Internals.REGISTER-DYNAMIC: '%*SUB-MAIN-OPTS', {
PROCESS::<%SUB-MAIN-OPTS> := {}
}

然后在模块中,这样写:

%*SUB-MAIN-OPTS = :named-anywhere;

或者更好的是:

%*SUB-MAIN-OPTS<named-anywhere> = True;

在尝试了这个之后,它似乎工作得很好。

事情是这样的 used to be there .

考虑到它会减慢每个 Raku 程序的速度,它被删除了。

虽然我认为它造成的任何减速仍然是一个问题,因为仍然存在的行必须查看是否存在该名称的动态变量。
(给出的理由更多,坦率地说,我不同意所有这些理由。)

关于main - 改变参数在传递给子 MAIN 之前的处理方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62239232/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com