Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to increment a scalar reference in Perl?

Say I have a number, $x = 0; and I want to increment it with a subroutine, but the subroutine won't be returning its value:

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

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

        ...

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

    return $list[$var++];
}

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

As-is, this will print aaaaaaaaaa forever instead of abcdefghij. If I replace increment($x) with increment(\$x), it converts the scalar address to a decimal number and increments that instead. In the above scenario, it ends up throwing an error because 25423331 or whatever isn't a valid array element.

If $x were an element in a hash or an array, I could pass the parent as a reference to have the original modified:

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

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

How can I modify the original value of a scalar reference?

like image 331
ND Geek Avatar asked Dec 25 '22 14:12

ND Geek


2 Answers

You can pass a reference to the variable to modify.

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

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

You could also take advantage of the fact that Perl passes by reference.

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

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

But hiding the increment as such is a really bad idea. Either iterate over a list,

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

Or write an iterator.

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

my $iter = make_iter('a'..'z');
while (my ($x) = $iter->()) {
   ...
}
like image 169
ikegami Avatar answered Dec 27 '22 10:12

ikegami


You need to dereference $var inside the subroutine, like this:

my $x = 0;

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

sub foo {
    my $y = shift;
    $$y++;
}
like image 34
Matt Jacob Avatar answered Dec 27 '22 11:12

Matt Jacob