radoina (1) [Avatar] Offline
#1
Hello Damian,

I am a newcomer to Perl. I am trying to read/understand your book "Object Oriented Perl". At the subchater 2.2.3 Closures, under "Anonymous subroutines and closures" page 57, there is this example:


sub hop_along
{
my ($from, $to, $step) = @_; # Unpack args
my $next = $from-$step; # Initialize counter
my $closure_ref = # Build closure
sub # that does the following...
{
$next+=$step; # Take a step
return if $next > $to; # undef if out of range
$_[0] = $next; # Otherwise set new value
return 1; # and succeed
};
return $closure_ref; # Return closure
}

$iterator = hop_along 1, 100, 7; # Create closure: hop_along is executed
# and returns the ref to the anon sub
while (defined($iterator->($next))) # Call closure
{
print $next, "
";
}

Even if I ran this example with debugger (-d option) I could not understand the call $iterator->($next). It it a call to the closure subroutine, referred to by $closure_ref. But the argument is $next. For every iteration of the while loop, $next (only inside the closure) has different values (1, 8, 15 etc.). I know that the call puts the argument in $_[0]. So, at each call, $_[0] should be 1, 8, 15 etc. But in the closure code, I don't see the value of $_[0] being used. Instead, the closure sets up $_[0] with the incremented value of $next and returns. And again, the next call to the closure doesn't use $_[0], but the value of $next. It seems to me that the closure doesn't use arguments, but only the current value of the lexical variable $next.
Also, at the moment of execution of 'print $next, "
";' line, $next should be undefined (the rules say that $next is only viewed inside the block where it's defined or by the closure that uses it). Still, it is printed alright.
I am not sure if I described well my problem. I would really appreciate I you would be so nice and explain the above call ($iterator->($next)) for me.

Thank you very much for your work at this book and for helping me,
Radu