加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

迭代器 – 尝试分配给字符串角色时“无法分配给不可变值”

发布时间:2020-12-15 21:49:01 所属栏目:大数据 来源:网络整理
导读:从 the example in the Iterable doc page开始 role DNA does Iterable { method iterator(){ self.comb.iterator }};my @a does DNA = 'GAATCC';.say for @a; # OUTPUT: ?G?A?A?T?C?C?? 我发现使用@声明它很奇怪,所以我把它改成了声明字符串的自然方式,$:
从 the example in the Iterable doc page开始
role DNA does Iterable {
  method iterator(){ self.comb.iterator }
};

my @a does DNA = 'GAATCC';
.say for @a; # OUTPUT: ?G?A?A?T?C?C??

我发现使用@声明它很奇怪,所以我把它改成了声明字符串的自然方式,$:

my $a does DNA = 'GAATCC';

但是失败了,有些令人困惑的“无法分配给不可变的价值”.无需现场指派,所以我们可以这样做:

my $a = 'GAATCC';
$a does DNA;
.say for $a;

这只是为了以后留下混合.但这只是打印字符串,而不关注Iterable mixin.让我们明确地调用它:

.say for $a.iterator;

它有点像以前一样,只打印$a.iterator的值,而不实际调用函数:

<anon|69>.new

这看起来像the same thing it’s going on in this other question.基线问题是我不明白Iterable真正做了什么角色,以及它在某个对象上调用迭代器时的确实做了什么.任何的想法?

解决方法

你的问题的标题指向一个错误.这个答案涵盖了bug以及您提出的其他隐含和显式问题.

背景

fails with a somewhat bewildering “Cannot assign to an immutable value”.

我认为这是一个错误.让我们从一些有效的代码开始:

my $a = 42;
say $a;          # 42
say WHAT $a;     # (Int)               type of VALUE currently ASSIGNED to $a
say WHAT VAR $a; # (Scalar)            type of VARIABLE currently BOUND to $a
$a = 42;         # works fine

在我的声明中,$a获得BOUND到新的Scalar container.标量容器通常隐藏自己.如果你询问$a类型是什么,你实际上得到的是当前分配给标量的值的类型(它“包含”的值).您需要VAR才能访问容器BOUND到$a.将=赋值给标量容器时,将指定的值复制到容器中.

role foo {}
$a does foo;     # changes the VALUE currently ASSIGNED to $a
                 # (NOT the VARIABLE that is BOUND to $a)
say $a;          # 42                  mixed in `foo` role is invisible
say WHAT $a;     # (Int+{foo})         type of VALUE currently ASSIGNED to $a
say WHAT VAR $a; # (Scalar)            type of VARIABLE currently BOUND to $a
$a = 99; say $a; # 99

确实将foo角色混合到了42.你仍然可以分配给$a,因为它仍然绑定到标量.

注意这两种用法的效果有很大不同:

my $a does foo;  # mixes `foo` into VARIABLE bound to $a
$a does foo;     # mixes `foo` into VALUE assigned to $a

错误

$a.VAR does foo; # changes VARIABLE currently BOUND to $a (and it loses the 42)
say $a;          # Scalar+{foo}.new    VALUE currently ASSIGNED to $a
say WHAT $a;     # (Scalar+{foo})      type of VALUE currently ASSIGNED to $a
say WHAT VAR $a; # (Scalar+{foo})      type of VARIABLE currently BOUND to $a

$a = 'uhoh';     # Cannot assign to an immutable value

它确实将foo角色混合到绑定到$a的Scalar中.似乎带有mixin的Scalar不再能够成功地用作容器,并且赋值失败.

这在我看来就像一个bug.

my $b does foo;  # BINDS mixed in VARIABLE to $b
$b = 'uhoh';     # Cannot assign to an immutable value

我的$b foo与我的$b有相同的结果; $b.VAR确实foo;所以你得到与上面相同的问题.

你困惑的其他事情

my $a = 'GAATCC';
$a does DNA;
.say for $a;

just prints the string,without paying any attention to the Iterable mixin.

因为$a VARIABLE仍然绑定到标量(如上面的背景部分所述),现在混合了DNA角色的VALUE与the decision process for uses about whether to call its argument’s .iterator method无关.

Let’s call it then explicitly … prints the value of $a.iterator,without actually calling the function:

.say for $a.iterator;

那么它确实称你的DNA角色为.iterator方法.但是在你的DNA角色的迭代器方法返回的self.comb结尾处有另一个.iterator调用,所以你就是那个二级.iterator.

解决方案今天有效

我认为布拉德的答案很好地涵盖了你的大部分选择.

如果你想使用$sigil,我认为你的does DNA gist和今天的P6一样好.

一天可能有效的解决方案

在一个理想的世界中,P6设计中的所有甜蜜都将在6.c和Perl 6的Rakudo编译器实现中完全实现.也许这包括编写这个并获得你想要的东西的能力:

class DNA is Scalar does Iterable { ... }
my $a is DNA = 'GAATCC';
.say for $a;

…代码与你在gist中的代码大致相同,只是DNA类是标量容器,因此新方法将是一个STORE方法或类似的方法,将传递的值赋给$!value属性或使用=分配给容器的某些值.

但相反,你得到:

is trait on $-sigil variable not yet implemented. Sorry.

因此,你今天最接近理想的=’string’来改变$a就是使用:= DNA.new(‘string’)进行绑定,就像你在你的要点中所做的那样.

请注意,您可以将任意复合容器绑定到@和%sigil变量.所以你可以看到事情最终会如何发挥作用.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读