变量在for循环中被覆盖

时间:2019-08-08 03:47:15

标签: raku

在for循环中,为另一个变量分配了一个值。已经分配了值的变量将从下一次迭代中分配值。最后,两个变量具有相同的值。 该代码用于验证文件中的数据。当我打印值时,它将为第一次迭代打印正确的值,但是在下一次迭代中,将更改在第一次迭代中分配的值。 当我在for循环中打印$ value3和$ value4的值时,它显示$ value4为null并显示$ 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;

}

2 个答案:

答案 0 :(得分:7)

TL; DR 不可能自信地回答您的问题。这是一个nanswer -在我将其写为一个 answer 的同时,在帮助您解决问题的意义上也可能是 not answer 。 / p>

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;

显示:

0.14168492246366005
(Any)
0.31843665763839857
0.31843665763839857

这不是语言或编译器中的错误。只是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

这将输出:

Iteration: 3
0.5779679442816953
(Any)
Iteration: 4
0.8650280000277686
0.8650280000277686

is rw吗?再看看。

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

  

避免混叠容器的一种方法是只使用=

(毫无疑问,这也是@ ElizabethMattijsen ++为什么要尝试使用=而不是:=的原因。)

您已经评论说,从:=更改为=没什么区别。

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

因此也许可以通过从:=切换到=来解决问题,但是在其他地方的某些代码中。 (也就是说,不仅要将:=全局替换为=。相反,请确保您了解它们的区别,然后适当地更改它们。您已经进行了测试套房,对吗?;))

如果您仍然被困,该如何前进

现在,您的问题已获得数票赞成,而无票数反对,您有两个答案(指向同一个问题)。

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

如果是...

添加了reddit注释,并尝试使用=而不是:=,并尝试使用最新的编译器,并对这些内容进行注释,这让我很高兴我没有拒绝您的问题,但是我还没有投票支持,这是有原因的。这是因为您的问题仍然缺少Minimal Reproducible Example

您回答了我关于制作MRE的建议:

  

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

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

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

答案 1 :(得分:6)

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

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

避免混叠容器的一种方法是只使用=

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

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

您还可以使用.self.<>

取消容器化值
my $old := $o.a.<>;
say $old; # 1

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

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