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

标签 class hash binding eval raku

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

    相关文章:

    c - C 中的哈希表不适用于字符串

    WPF 绑定(bind)到局部变量

    javascript - Vue 绑定(bind)将数据发送到表

    asp.net - 无法为 'localhost' 生成绑定(bind)重定向。已添加具有相同 key 的项目

    java - 对象数组声明

    javascript - 如何通过单击 100 个具有相同类别的框中的任何一个来打开模式?

    javascript - 开发自己的 "Hash"算法

    oop - Matlab相当于调用内部静态类

    class - 将 Plantronics SDK 与 Delphi 应用程序一起使用

    ruby-on-rails - Rails 中带有哈希值的不允许的参数