gpt4 book ai didi

for-loop - 标量值在推送后是否受到影响......(Raku)

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

我很难理解推送 Scalar 何时以及为何持有该值容器在推送后受到影响。我将尝试用两个程式化的示例来说明我在更复杂的情况下遇到的问题。

*示例 1 * 在第一个示例中,标量 $i被插入数组 @b作为 List 的一部分。推送后,标量保存的值将在 for 循环的后续迭代中使用 $i++ 显式更新。操作说明。这些更新对数组 @b 中的值有影响:在 for 循环结束时,@b[0;0]等于3 ,不再是2 .

my @b;
my $i=0;
for 1..3 -> $x {
$i++;
say 'Loose var $i: ', $i.VAR.WHICH, " ", $i.VAR.WHERE;
if $x == 2 {
@b.push(($i,1));
say 'Pushed $i : ', @b[0;0].VAR.WHICH, " ", @b[0;0].VAR.WHERE;
}
}
say "Post for-loop";
say "Array : ", @b;
say 'Pushed $i : ', @b[0;0].VAR.WHICH, " ", @b[0;0].VAR.WHERE;

输出示例1:

Loose var $i: Scalar|94884317665520 139900170768608
Loose var $i: Scalar|94884317665520 139900170768648
Pushed $i : Scalar|94884317665520 139900170768648
Loose var $i: Scalar|94884317665520 139900170768688
Post for-loop
Array : [(3 1)]
Pushed $i : Scalar|94884317665520 139900170768688

* 示例 2 * 在第二个示例中,标量 $i是循环变量。即使$i在推送后更新(现在是隐式而不是显式), $i 的值在数组 @c 推送后发生变化;即在for循环之后,它仍然是2 ,不是3 .

my @c;
for 1..3 -> $i {
say 'Loose var $i: ', $i.VAR.WHICH, " ", $i.VAR.WHERE;
if $i == 2 {
@c.push(($i,1));
say 'Pushed $i : ', @c[0;0].VAR.WHICH, " ", @c[0;0].VAR.WHERE;
}
}
say "Post for-loop";
say "Array : ", @c;
say 'Pushed $i : ', @c[0;0].VAR.WHICH, " ", @c[0;0].VAR.WHERE;;

输出示例2:

Loose var $i: Scalar|94289037186864 139683885277408
Loose var $i: Scalar|94289037186864 139683885277448
Pushed $i : Scalar|94289037186864 139683885277448
Loose var $i: Scalar|94289037186864 139683885277488
Post for-loop
Array : [(2 1)]
Pushed $i : Scalar|94289037186864 139683885277448

问题:为什么是 $i@b在示例 1 中,推送后更新,而 $i@c示例 2 中不是吗?

编辑:根据 @timotimo 的评论,我添加了 .WHERE 的输出在示例中。这显示了 $i 的(哪个/逻辑)标量标识。保持不变,而其内存地址通过各种循环迭代而变化。但它并没有解释为什么在示例 2 中推送的标量仍然与相同的 WHICH 身份和旧地址(“448”)相关联。

最佳答案

标量值只是一个容器。您可以将它们视为一种智能指针,而不是原始值。

如果你做作业

$foo = "something"; #or
$bar++;

您正在更改标量值,容器保持不变。

考虑

my @b; 
my $i=0;
for 1..5 -> $x {
$i++;
@b.push(($i<>,1)); # decontainerize $i and use the bare value
}
say @b;

my @b; 
my $i=0;
for 1..5 -> $x {
$i := $i + 1; # replaces the container with value / change value
@b.push(($i,1));
}
say @b;

两者都按预期工作。但是:在这两种情况下,列表中的内容不再可变,因为没有容器。

@b[4;0] = 99; 

因此会死亡。那么就使用循环变量吧?

没有。

for 1..5 -> $x { 
@b.push(($x,1)); #
}
@b[4;0] = 99; #dies

即使我们迭代可变事物的列表。

my $one = 1;
my $two = 2;
my $three = 3;
my $four = 4;
my $five = 5;

for ($one, $two, $three, $four, $five) -> $x {
@b.push(($x,1));
}
@b[4;0] = 99; #dies

因此,这里没有发生别名,相反,循环变量始终是同一个容器,并获取来自其他容器的分配值。

不过我们可以做到这一点。

for ($one, $two, $three, $four, $five) <-> $x { 
@b.push(($x,1));
}
@b[4;0] = 99; # works

for ($one, $two, $three, $four, $five) -> $x is rw {
@b.push(($x,1));
}
@b[4;0] = 99; # works too

使“事物”可变的一种方法是使用中间变量。

for 1..5 -> $x { 
my $j = $x;
@b.push(($j,1)); # a new container
}
@b[4;0] = 99;

工作正常。或者在原始上下文中更短、更多

my @b; 
my $i=0;
for 1..5 -> $x {
$i++;
@b.push((my $ = $i, 1)); # a new anonymous container
}
@b[4;0] = 99;
say @b; # [(1 1) (2 1) (3 1) (4 1) (99 1)]

另请参阅:

https://perl6advent.wordpress.com/2017/12/02/#theoneandonly https://docs.perl6.org/language/containers

关于for-loop - 标量值在推送后是否受到影响......(Raku),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58249670/

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