从迭代器生成序列

时间:2019-01-16 01:36:18

标签: perl6

我正在尝试制作一个迭代器,然后从中构建一个序列,但是它没有按照我认为的方式运行。怎么了?

这是我的基础班:

class Foo {
    has $.x = 0;
    has $.max = 3;

    method val() {
        (++$!x > $!max) ?? () !! ($!x, "string $!x")
    }
}

my $foo = Foo.new;
say $foo.val.perl for ^4;

# (1, "string 1")
# (2, "string 2")
# (3, "string 3")
# ()

它只会迭代到max,然后返回(),以我认为的方式工作。

然后我从中构建一个Iterator,仅使用一个pull-one()方法。

class Foo-Iterator does Iterator {
    has Foo $.foo;

    method pull-one() {
        $!foo.val || IterationEnd
    }
}

my $iter = Foo-Iterator.new(foo => Foo.new);
$iter.pull-one.perl.say for ^4;

# (1, "string 1")
# (2, "string 2")
# (3, "string 3")
# IterationEnd

它仍然按照我期望的方式运行。

如果我使用Seq访问它,它仍然可以正常工作:

.perl.say for Seq.new: Foo-Iterator.new(foo => Foo.new);
# (1, "string 1")
# (2, "string 2")
# (3, "string 3")

这仍然是我期望看到的,与迭代器返回的结果相同。

最后,我将Seq存储在@变量中并打印结果:

my @seq = Seq.new: Foo-Iterator.new(foo => Foo.new);
.perl.say for @seq;
# $(4, "string 1")
# $(4, "string 2")
# $(4, "string 3")

这是怎么回事?似乎使用的是变量的后一个值,而不是使用在推入式call()时它具有的值(字符串将其强制为值)。 Seq是否将其作为容器而不是值返回?这种懒惰在起作用吗,直到请求时才拉动,以便获得更高的值?

如果我让val()返回+$!x而不是返回$!x,那似乎是在获取价值并给了我想要的东西,我只是想了解自己的行为

1 个答案:

答案 0 :(得分:7)

我对C:\Users\your_user_name\AppData\Local\Atlassian\SourceTree\git_local\usr\bin进行了4处更改:keytool -alias MyKey -exportcert -keystore MyKey.keystore | C:\Users\your_user_name\AppData\Local\Atlassian\SourceTree\git_local\usr\bin\xxd -p | C:\Users\your_user_name\AppData\Local\Atlassian\SourceTree\git_local\usr\bin\tr -d "[:space:]"Foodoes Iterator,然后用pull-one断定IterationEnd。 >

当您真的要在容器内传递值时,您的方法正在传递%!x的容器,因此它需要<>
您在其余的代码中没有注意到它的原因是,数组分配是唯一的$!x

我做了其余的更改,因为它已经具有状态,并且只能运行一次。 $!x<>到底应该如何工作。对于您的代码,为eager添加基本上仅重命名方法的另一个对象是没有意义的。

Iterator

现在可以使用

Iterator

假设您的示例太简单了,并且有一个单独的class Foo does Iterator { # ^-----------^ has $.x = 0; has $.max = 3; method pull-one() { # ^------^ (++$!x > $!max) ?? IterationEnd !! ($!x<>, "string $!x") # ^----------^ ^^ } } 的充分理由,那么为什么要使用变异的my $seq = Seq.new( Foo.new ); for $seq<> { .say } # (1 string 1) # (2 string 2) # (3 string 3) my @seq = Seq.new( Foo.new ); for @seq { .say } # (1 string 1) # (2 string 2) # (3 string 3) 方法呢?

Iterator

现在可以使用它。

val