在 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/