是否可以在 Perl 中增加标量引用?

Is it possible to increment a scalar reference in Perl?

假设我有一个数字,$x = 0;,我想用子程序增加它,但子程序不会返回它的值:

sub increment {
    my ($var) = @_;

    my @list = (
        'a',
        'b',
        'c',

        ...

        'x',
        'y',
        'z'
    );

    return $list[$var++];
}

while ($x < 10) {
    print increment($x);
}

照原样,这将永远打印 aaaaaaaaaa 而不是 abcdefghij。如果我将 increment($x) 替换为 increment($x),它会将标量地址转换为十进制数并改为递增。在上面的场景中,它最终会抛出一个错误,因为 25423331 或任何不是有效数组元素的东西。

如果 $x 是散列或数组中的一个元素,我可以将父项作为参考传递以修改原始元素:

$x = {'val' => 0};
while ($x->{'val'} < 10) {
    print increment($x);
}

sub increment {
    ...
    return $list[$var->{$val}++];
}

如何修改标量引用的原始值?

您需要在子例程中取消引用 $var,如下所示:

my $x = 0;

say $x;  # prints 0
foo($x);
say $x;  # prints 1

sub foo {
    my $y = shift;
    $$y++;
}

您可以传递对变量的引用来修改。

sub increment {
    my ($ref) = @_;
    ++$$ref;
}

my $i = 0;
say $i;  # prints 0
increment($i);
say $i;  # prints 1

您还可以利用 Perl passes by reference.

sub increment {
    ++$_[0];
}

my $i = 0;
say $i;  # prints 0
increment($i);
say $i;  # prints 1

但是这样隐藏增量是一个非常糟糕的主意。遍历列表,

for my $x ('a'..'z') {
   ...
}

或者写一个迭代器。

sub make_iter {
   my @list = @_;
   return sub {
      return @list ? shift(@list) : ();
   };
}

my $iter = make_iter('a'..'z');
while (my ($x) = $iter->()) {
   ...
}