I'm attempting to call a nested recursive perl function, but I can't tack the correct syntax.
Question: What is the correct syntax to perform a recursive call for a nested function (if nested functions should be recursively called at all)?
Answer: Refer to suggested pseudocode in the accepted answer.
Here is a pseudocode snippet:
use Scalar::Util;
sub outerfunction {
my $innerfunction = sub {
# Do something
innerfunction();
# Do other things
};
Scalar::Util::weaken($innerfunction);
&$innerfunction(@_);
};
I've tried to invoke innerfunction as the following (with the consequential error messages):
innerfunction
Undefined subroutine &main::innerfunction
&innerfunction
Undefined subroutine &main::innerfunction
&$innerfunction
Global symbol "$innerfunction" requires explicit package name
I've also tried to declare the innerfunction as local, but receive the following:
Global symbol "$innerfunction" requires explicit package name
I don't have much experience with interpreted languages, so any incidental commentary related to memory/stack leakage/ corruption or other dangers with the above pseudocode (other than system limits on recursion) would be greatly appreciated as well.
Thanks! perl v5.10.1 running on Linux 2.6.34.7-61.fc13.x86_64
The innerfunction()
syntax is only available for subroutines that have been installed into the symbol table (such as the sub NAME {...}
syntax does). You need to call your inner function as $innerfunction->()
or &$innerfunction()
, but where you are having trouble is with the scoping of the $innerfunction
lexical.
When you declare a variable with my
, the variable is in scope after that statement ends. So you need to split your declaration:
my $innerfunction;
$innerfunction = sub {
...
$innerfunction->();
...
};
To break the circular reference with weaken
the usual pattern is:
use Scalar::Util;
sub outer_function {
my $weak_ref;
$weak_ref = my $strong_ref = sub {
# Do something
$weak_ref->();
# Do other things
};
Scalar::Util::weaken($weak_ref);
return $strong_ref;
};
So now, as soon as $strong_ref
goes out of scope, the subroutine will be garbage collected.
sub outer_function {
local *inner_function = sub {
# Do something
inner_function();
# Do other things
};
inner_function();
};
is almost as good as the following, yet much much clearer:
use Scalar::Util qw( weaken );
sub outer_function {
my $weak_ref;
my $strong_ref = sub {
# Do something
$weak_ref->();
# Do other things
};
weaken($weak_ref = $strong_ref); # Avoid memory leak.
$strong_ref->();
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With