uzl*_*xxx 5 iterator perl6 raku
假设我们有以下组成角色的类Iterable
:
class Word-Char does Iterable {
has @.words;
method !pairize($item) {
return $item => $item.chars;
}
method iterator( Word-Char:D: ) {
@!words.map({self!pairize($_)}).rotor(1).iterator
}
}
Run Code Online (Sandbox Code Playgroud)
我可以Positional
在对象构造期间将对象分配给变量,然后对该变量进行迭代:
my @words = Word-Char.new: words => <the sky is blue>;
.say for @words;
Run Code Online (Sandbox Code Playgroud)
输出:
(the => 3)
(sky => 3)
(is => 2)
(blue => 4)
Run Code Online (Sandbox Code Playgroud)
但是,如果要传递对象该怎么办?我如何确保它仍然可迭代?:
my $w = Word-Char.new: words => <the sky is blue>;
sub f( $w ) {
.say for $w
}
f($w);
Run Code Online (Sandbox Code Playgroud)
输出:
Word-Char.new(words => ["the", "sky", "is", "blue"])
Run Code Online (Sandbox Code Playgroud)
目标:
通过使用Iterable
,Iterator
或两者兼而有之,我想,如果可能的话,要能够遍历任何地方实现这些角色的类的实例对象。现在我知道,通过在对象构造过程中将实例对象分配给Positional
变量,我可以获得类提供的可迭代项,但这不是我想要的。相反,我想传递对象本身,并在我认为有需要的地方/地方对其进行遍历。
在处理具有迭代器角色的标量值时,完成您要尝试的操作的最简单方法是告诉perl6您的标量值是可迭代的。您可以通过将其后缀来实现[]
。您的示例如下所示:
my $w = Word-Char.new: words => <the sky is blue>;
.say for $w[]
Run Code Online (Sandbox Code Playgroud)
另一件事....
您的迭代代码存在一个错误,即它不会在返回之前重置自身IterationEnd
。快速修复如下所示:
class Word-Char does Iterable does Iterator {
has @.words;
has Int $!index = 0;
method !pairize($item) {
return $item => $item.chars;
}
method iterator() {self}
method pull-one( --> Mu ) {
if $!index < @!words.elems {
my $item = @!words[$!index];
$!index += 1;
return self!pairize($item);
}
else {
$!index = 0;
return IterationEnd;
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,这意味着您必须将所有迭代逻辑(及其属性)保留在主类中。另一种方法是使用匿名类,而不是使用self
:
class Word-Char does Iterable {
has @.words;
method !pairize($item) {
return $item => $item.chars;
}
method iterator() {
my @words = @!words;
class :: does Iterator {
has $.index is rw = 0;
method pull-one {
return IterationEnd if $!index >= @words.elems;
@words[$!index++];
}
}.new;
}
}
Run Code Online (Sandbox Code Playgroud)
上面的优点是您可以使迭代逻辑更整洁,并与对象的其余部分隔离。您也不必担心重置状态。
归档时间: |
|
查看次数: |
133 次 |
最近记录: |