At the following example I want to alter the value of $counter variable ,
but without using the the $iter code reference.
I 've tried many tricks using __ANON__ but without luck . Can you help ?
my $iter = Create_counter( 37);
for (1..3)
{
print "$_) ". $iter->() ."\n"
}
sub Create_counter
{
my $counter = $_[0];
return sub
{
$counter++
}
}
Dear George,
The problem with trying to alter the $counter variable is that it
is a variable that only gets modified inside the Create_counter()
subroutine and the function it returns.
Basically, you're using a closure. Read up on "perldoc -q closure"
for a better idea of what a closure is.
When you assign the subroutine reference to $iter with the line:
my $iter = Create_counter(37);
you're giving $iter the only power to modify the $counter variable
that was created in the call to Create_counter() . From here on, the
only way to modify that specific instance of $counter is to call $iter-
You can change all that if you modify the code, however. If you
change the Create_counter() subroutine to look like:
sub Create_counter
{
my $counter = $_[0];
return \$counter, sub { $counter++ }
}
then you can call it like this:
my ($counterRef, $iter) = Create_counter(37);
and you can see and modify the value of the $counter by printing or
assigning to $$counterRef (note the double '$' -- that's not a typo).
What's more is that you can still call Create_counter() the old way,
like this:
my $iter = Create_counter(37);
which will just discard the $counterRef part (due to assigning to a
scalar). However, if you do this, then you lose the ability to
observe and modify the $counter instance that $iter->() uses (other
than just calling $iter->(), of course).
If you prefer to avoid references, you can write Create_counter()
this way:
sub Create_counter
{
my $counter = $_[0];
return sub { $counter }, # getter
sub { $counter = $_[0] }, # setter
sub { $counter++ } # iterator
}
This will allow you to write code like this:
my ($getter, $setter, $iter) = Create_counter(37);
print $iter->(); # prints 37 and sets $counter to 38
print $getter->(); # prints out $counter, which is 38
$setter->(5); # sets $counter to 5
print $iter->(); # prints 5 and sets $counter to 6
So if you want to be able to read/modify the $counter variable that
$iter->() uses (without using $iter), you have to somehow return
access to it, by either returning a reference to it, or by returning
another sub { } that can read/modify it.
I hope this helps, George.
Have a great day!
-- Jean-Luc