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

时间:2015-09-02 16:32:09

标签: perl pass-by-reference

假设我有一个数字$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}++];
}

如何修改标量参考的原始值?

2 个答案:

答案 0 :(得分:6)

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

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 = 'a'..'z';
   return sub {
      return @list ? () : shift(@list);
   };
}

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

答案 1 :(得分:2)

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

my $x = 0;

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

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