2015-09-02 25 views
2

说我有一个数字,$x = 0;我想用一个子程序来增加它,但子程序不会返回它的值:是否可以在Perl中增加标量引用?

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}++]; 
} 

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

+1

请注意 - 你并不需要这么做。你可以改为'我的$字母='a';打印$ letter ++(1..10);' – Sobrique

+4

尽管我提供了一个答案,可以满足您的要求,但我通常会建议您避免这样做。让循环索引“在一定距离”递增是有点让人迷惑的。 –

+1

@Sobrique我不能相信这是有效的,但行为甚至[记录](http://perldoc.perl.org/perlop.html#Auto-increment-and-Auto-decrement)。谢谢你今天教我新东西。 –

回答

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->()) { 
    ... 
} 
+0

@DaveSherohman:在任何通过引用传递的语言中,如果将传递引用参数分配给另一个常规局部变量,则该变量是原始的独立副本。 – newacct

+1

是的,我站在纠正。我现在恰好在YAPC :: EU,所以我找到了一个Perl 5核心开发人员,并询问了@_与别名之间的区别。他的回答是“哦,这是一个传递参考”。由于我错了,这个评论讨论不可能对未来的任何人有所帮助,所以我删除了我以前的评论。 –

2

您需要取消引用$var子程序里面,像这样:

my $x = 0; 

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

sub foo { 
    my $y = shift; 
    $$y++; 
} 
相关问题