变量在for循环中被覆盖

Abe*_*eer 4 perl6 raku

在for循环中,为另一个变量分配了一个值。已经分配了值的变量将从下一次迭代中分配值。最后,两个变量具有相同的值。该代码用于验证文件中的数据。当我打印值时,它将为第一次迭代打印正确的值,但是在下一次迭代中,将更改在第一次迭代中分配的值。当我在for循环中打印$ value3和$ value4的值时,它对$ value4显示空值,对$ value3显示一些值,但是在下一次迭代中,$ value3的值将被$ value4的值覆盖

我已经尝试过rakudo perl 6.c

my $fh= $!FileName.IO.open;
my $fileObject = FileValidation.new( file => $fh );

for (3,4).list {

  put "Iteration: ", $_;
  if ($_ == 4) {
    $value4 := $fileObject.FileValidationFunction(%.ValidationRules{4}<ValidationFunction>, %.ValidationRules{4}<Arguments>);
  }

  if ($_ == 3) {
    $value3 := $fileObject.FileValidationFunction(%.ValidationRules{3}<ValidationFunction>, %.ValidationRules{3}<Arguments>);
  }

  $fh.seek: SeekFromBeginning;

}
Run Code Online (Sandbox Code Playgroud)

rai*_*iph 6

TL; DR不可能自信地回答您的问题。这是一个nanswer -一个答案在这个意义上,我写它作为一个也很可能不是一个答案在帮助你的感觉解决您的问题。

is rw吗 初看。

is rw一次例行或类别属性特征意味着它返回一个包含一个值,而不是只返回一个值的容器。

如果然后对该容器进行别名,则可以得到您描述的行为。

例如:

my $foo;
sub bar is rw { $foo = rand }
my ($value3, $value4);
$value3 := bar;
.say for $value3, $value4;
$value4 := bar;
.say for $value3, $value4;
Run Code Online (Sandbox Code Playgroud)

显示:

0.14168492246366005
(Any)
0.31843665763839857
0.31843665763839857
Run Code Online (Sandbox Code Playgroud)

这不是语言或编译器中的错误。只是P6代码可以完成应有的工作。

同一事物的较长版本

也许以上内容与您的代码相去甚远,令人迷惑。因此,这就像包裹在您提供的代码中一样。

spurt 'junk', 'junk';

class FileValidation {
  has $.file;
  has $!foo;
  method FileValidationFunction ($,$) is rw { $!foo = rand }
}

class bar {
  has $!FileName = 'junk';
  has %.ValidationRules =
    { 3 => { ValidationFunction => {;}, Arguments => () },
      4 => { ValidationFunction => {;}, Arguments => () } }

  my ($value3, $value4);

  method baz {
    my $fh= $!FileName.IO.open;
    my $fileObject = FileValidation.new( file => $fh );
    my ($value3, $value4);

    for (3,4).list {

      put "Iteration: ", $_;
      if ($_ == 4) {
        $value4 := $fileObject.FileValidationFunction(
          %.ValidationRules{4}<ValidationFunction>, %.ValidationRules{4}<Arguments>);
      }

      if ($_ == 3) {
        $value3 := $fileObject.FileValidationFunction(
          %.ValidationRules{3}<ValidationFunction>, %.ValidationRules{3}<Arguments>);
      }

      $fh.seek: SeekFromBeginning;

      .say for $value3, $value4
    }
  }
}

bar.new.baz
Run Code Online (Sandbox Code Playgroud)

输出:

Iteration: 3
0.5779679442816953
(Any)
Iteration: 4
0.8650280000277686
0.8650280000277686
Run Code Online (Sandbox Code Playgroud)

is rw吗 再看看。

布拉德和我提出了基本相同的答案(在同一时间;比布拉德领先我一分钟,但谁在计数?我的意思是除了我之外吗?:)),但布拉德很好地解决了这个问题:

避免对容器使用别名的一种方法是使用=

(毫无疑问,这也是为什么@ ElizabethMattijsen ++询问尝试=代替的原因:=。)

您已经评论说,从更改:==没有任何区别。

但是,大概您没有在整个代码库中从更改为:==而是只是(等同于)共享代码中的两者。

因此,也许这个问题仍然可以通过切换固定:==,但在某些代码的其他地方。(也就是说,不仅要全局替换:==。而是要确保您了解它们之间的区别,然后适当地进行更改。您已经有了一个测试套件,对吗?))

如果仍然陷于困境,如何前进

现在,您的问题已获得数次赞成,而无人赞成,并且您有两个答案(指向同一个问题)。

但是也许我们的答案还不够好。

如果是这样的话...

添加reddit注释,然后尝试=代替:=,并尝试最新的编译器,并对这些事情进行注释,这让我很高兴我没有对您的问题进行表决,但是我尚未对它进行表决,这是有原因的。这是因为您的问题仍然缺少最小可重现的示例

您回应了我关于生成MRE的建议,其中包括:

问题是我无法在更简单的环境中复制它

我认为这是你的情况,但你可以想像,这意味着我们不能自信地复制它在所有。这可能是您出于某种原因而倾向于使用的方式,但是它违反了SO指南(在上面的链接中),如果当前答案不够充分,那么明智的前进方法是让您完成共享复制代码所需的工作你的问题。

如果太大,请不要将其粘贴到您的问题中,而应链接到它。也许您可以使用按钮在glot.io上设置它+以使用多个文件(我认为最多可以有6个文件,另外还有一个标准输入)。如果没有,也许可以通过gist.github.com进行修改,如果可以的话,我可以在glot.io上为您设置。


Bra*_*ert 5

可能发生的情况是,您返回的是容器而不是值,然后将容器别名为变量。

class Foo {
    has $.a is rw;
}

my $o = Foo.new( a => 1 );

my $old := $o.a;
say $old; # 1

$o.a = 2;
say $old; # 2
Run Code Online (Sandbox Code Playgroud)

避免对容器使用别名的一种方法是使用=

my $old = $o.a;
say $old; # 1

$o.a = 2;
say $old; # 1
Run Code Online (Sandbox Code Playgroud)

您也可以使用.self或取消包装值.<>

my $old := $o.a.<>;
say $old; # 1

$o.a = 2;
say $old; # 1
Run Code Online (Sandbox Code Playgroud)

(请注意,.<>上面可能是.self或仅仅是<>。)