Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
443 views
in Technique[技术] by (71.8m points)

iterator - "Cannot assign to immutable value" when trying to assign to a string + role

Starting with 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?? 

I found it weird it's declared using the @, so I changed it to the natural way of declaring strings, $:

my $a does DNA = 'GAATCC';

But that fails with a somewhat bewildering "Cannot assign to an immutable value". No need to assign on the spot, so we can do:

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

Which just leaves mixing-in for later. But that just prints the string, without paying any attention to the Iterable mixin. Let's call it then explicitly:

.say for $a.iterator;

it does kinda the same thing as before, only it prints the value of $a.iterator, without actually calling the function:

<anon|69>.new

This looks like the same thing it's going on in this other question. Baseline question is I don't understand what role Iterable really does, and what for really does and when it is calling iterator on some object. Any idea?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I don't think this line does what you think it does:

my @a does DNA = 'GAATCC';

It is the same as:

my @a := [ 'GAATCC', ];
@a does DNA;

Basically the .comb call coerces the array into a Str, and splits that into characters.


If you instead did this:

my @a = 'GAATCC' but DNA;

Which is basically the same as

my @a := Seq.new(('GAATCC' but DNA).iterator).Array;

Note that @ variables store Positional values not Iterable values.


The thing you want is

my $a = 'GAATCC' but DNA;

$a.map: &say;

If you want to be able to use for you can't use a variable with a $ sigil

my a = 'GAATCC' but DNA;

.say for a;

You may want to add Seq list List etc methods to DNA.

role DNA does Iterable {
  method iterator(){
    self.comb.iterator
  }
  method Seq(){
    Seq.new: self.iterator
  }
  method list(){
    # self.Seq.list
    List.from-iterator: self.iterator
  }
}

my $a = 'GAATCC' but DNA;
.say for @$a;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...