gpt4 book ai didi

class - 关于 Raku 中 EVAL 中的哈希绑定(bind)的问题

转载 作者:行者123 更新时间:2023-12-03 17:08:07 24 4
gpt4 key购买 nike

在 EVAL 中绑定(bind)哈希时遇到了一些我不理解的事情。在 EVAL 之外绑定(bind)散列按预期工作。 EVAL 中的未绑定(bind)哈希按预期工作。但是在 EVAL 中绑定(bind)散列并不像我预期的那样工作。 (我的期望可能是错误的。)这是代码:
这有效:

#!/usr/bin/env raku

class Hash::Test does Associative {
has %.hash;

multi method STORE(@pairs) {
for @pairs -> $pair {
self.STORE: $pair
}
}

multi method STORE(Pair $pair) {
%!hash{$pair.key} = $pair.value;
}
}

no strict;
%hash-test := Hash::Test.new;
%hash-test = foo => 'bar', baz => 'quux';
say %hash-test;
输出:
$ ./hash-binding-works.raku 
Hash::Test.new(hash => {:baz("quux"), :foo("bar")})
这有效:
#!/usr/bin/env raku

class Foo {
use MONKEY-SEE-NO-EVAL;

method eval(Str $code) {
EVAL $code;
}
}

my $code = q:to/END/;
no strict;
%hash = foo => 'bar', baz => 'quux';
END

Foo.eval: $code;
say %Foo::hash;
输出:
$ ./hash-EVAL-works.raku 
{baz => quux, foo => bar}
但这不起作用:
#!/usr/bin/env raku

class Hash::Test does Associative {
has %.hash;

multi method STORE(@pairs) {
for @pairs -> $pair {
self.STORE: $pair
}
}

multi method STORE(Pair $pair) {
%!hash{$pair.key} = $pair.value;
}
}

class Foo {
use MONKEY-SEE-NO-EVAL;

method eval(Str $code) {
EVAL $code;
}
}

my $code = q:to/END/;
no strict;
%hash-test := Hash::Test.new;
%hash-test = foo => 'bar', baz => 'quux';
say %hash-test;
END

no strict;
Foo.eval: $code;
say %Foo::hash-test;
输出:
$ ./hash-EVAL-does-not-work.raku 
Hash::Test.new(hash => {:baz("quux"), :foo("bar")})
{}
Hash::Test 不是我正在使用的真正类(class),而是我打高尔夫球的目的。谁能解释这里发生了什么?谢谢!

最佳答案

TL;DR no strict; 通过隐式 our declarator 自动声明包变量. our通过隐式 my 声明包变量绑定(bind)到同名隐式包符号的词法变量声明符。您的代码破坏了该绑定(bind),从而破坏了您的代码。要解决它,请以另一种方式说同样的话。
解决方案no strict;没有帮助,所以我们摆脱了它。 our 也是如此.相反,我们声明一个 my词法变量,做我们需要/可以做的一切,然后,在代码的末尾将是 EVAL d、创建包变量并将其绑定(bind)到存储在词法中的值。

my $code = q:to/END/;
my %hash is Hash::Test;
%hash = foo => 'bar', baz => 'quux';
OUR::<%hash-test> := %hash;
END

Foo.eval: $code;
say %Foo::hash-test; # Hash::Test.new(hash => {:baz("quux"), :foo("bar")})
意外的解释
no strict; 下没有显式声明符声明的变量隐式声明 our变量:
no strict;
%hash-test = :a;
say MY::<%hash-test>; # {a => True}
say OUR::<%hash-test>; # {a => True}
换句话说,上面前两行的净效果相当于:
our %hash-test = :a;
反过来, our变量隐式声明 my变量并遵循 this SO 中显示的逻辑.所以这段代码:
no script;
%hash-test := ...;
正在这样做:
(my %hash-test := $?PACKAGE.WHO<%hash-test>) := ...;
它创建了一个词法 %hash-test符号和一个包 %hash-test符号,并绑定(bind)它们——该绑定(bind)对于 our 的正常运行至关重要变量——然后立即打破这个基本绑定(bind)。
此后,无论您的代码的其余部分做什么,它只对词法 %hash-test 执行此操作。变量的版本,保留包符号版本 %hash-test高而干燥,以便它稍后会自动生成一个空哈希。

正如 jnthn 在我一开始链接的 SO 下面的评论中所说:

We certainly could warn that binding to an our variable is pointless


但目前没有警告。

正如您在下面的评论中解释的那样,当您尝试使用 %hash-test is Hash::Test 时编译器神秘地认为你已经写了“连续两个词”。正如我在评论中解释的那样,这是由于您声明 our 时的上述诡计。变量使用通常的语法(或隐式使用 no strict; )。

要解决以上所有问题,请忘记 no strict; , 忘记使用 our ,而是:
  • 使用词汇来完成设置值的工作;
  • 最后用 OUR::<%hash-test> 创建包符号并将其绑定(bind)到词法的值。
  • 关于class - 关于 Raku 中 EVAL 中的哈希绑定(bind)的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66268489/

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