gpt4 book ai didi

raku - 如何将 .lines Seq 分配给变量并对其进行迭代?

转载 作者:行者123 更新时间:2023-12-04 03:03:12 25 4
gpt4 key购买 nike

将迭代器分配给变量显然会改变 Seq行为。例如。

use v6;

my $i = '/etc/lsb-release'.IO.lines;
say $i.WHAT;
say '/etc/lsb-release'.IO.lines.WHAT;
.say for $i;
.say for '/etc/lsb-release'.IO.lines;

结果是:
(Seq)
(Seq)
(DISTRIB_ID=Ubuntu DISTRIB_RELEASE=18.04 DISTRIB_CODENAME=bionic DISTRIB_DESCRIPTION="Ubuntu 18.04.1 LTS")
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.1 LTS"

因此,一旦分配,我只会得到序列的字符串表示形式。我知道我可以使用 .say for $i.lines获得相同的输出,但我不明白已分配和未分配的迭代器/序列之间的区别。

最佳答案

Perl 6 中的赋值总是关于将某些东西放入其他东西中。

分配到 Scalar ( $ sigil) 将分配的事物存储到 Scalar容器对象,这意味着它将被视为单个项目;这就是为什么for $item { }不会进行迭代。有多种方法可以克服这一点;概念上最简单的方法是使用 <>后缀运算符,去掉任何 Scalar容器:

my $i = '/etc/lsb-release'.IO.lines;
.say for $i<>;

还有滑动运算符(“flatten into”),它将实现相同的效果:
my $i = '/etc/lsb-release'.IO.lines;
.say for |$i;

分配到 Array将 - 除非右侧标记为惰性 - 对其进行迭代并将每个元素存储到 Array .因此:
my @i = '/etc/lsb-release'.IO.lines;
.say for @i;

可以,但它会急切地将所有行读入 @i在循环开始之前。这对于小文件是可以的,但对于大文件来说不太理想,我们可能更喜欢懒惰地工作(也就是说,一次只将一点文件拉入内存)。可以尝试:
my @i = lazy '/etc/lsb-release'.IO.lines;
.say for @i;

但这无助于保留问题;它只是意味着随着迭代的发生,数组将从文件中延迟填充。当然,有时我们可能想要多次遍历这些行,在这种情况下赋值为 Array将是最好的选择。

相比之下,声明一个符号并将其绑定(bind)到该符号:
my \i = '/etc/lsb-release'.IO.lines;
.say for i;

根本不是“投入”操作;它只是使符号 i究竟是什么 lines返回。这比将其放入 Scalar 中要清楚得多。容器只能再次取出。它对读者来说也更容易一些,因为 my \foo = ...永远不会被反弹,因此读者不需要在以后的代码中查找任何潜在的更改。

最后一点,值得知道 my \foo = ... form 实际上是一个绑定(bind),而不是一个赋值。 Perl 6 允许我们用 = 来编写它。运算符而不是强制 := , 即使在这种情况下语义是 :=语义。这只是带有初始化程序的声明与普通赋值稍有不同的众多情况之一,例如 has $!foo = rand实际上在每个对象实例化上运行分配,而 state $foo = rand仅当我们在当前闭包克隆的第一个条目上时才运行它。

关于raku - 如何将 .lines Seq 分配给变量并对其进行迭代?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52558578/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com