是否可以在 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->()) {
...
}
假设我有一个数字,$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->()) {
...
}