I'm asking this because of mod_perl. Mod_perl treats your whole script as one big subroutine called "handler". If you declare a subroutine inside, it will cause problems. That's why I quote the example above.

You can't do that. You can only call the inner rtn from INSIDE the first rtn, and THATS only if the parser is having a good day. It has to do with the way scripts are parsed. Spaghetti code is just bad programming anyway. Even if you DO get it to work, the next version of Perl could kill your code! Consider having 2 separate subrtns, thats the right way to do it, and you know it will continue to work on new Perl versions.

first off, perl does not support nested sub declarations so do try to do it. it doesn't do what you think it does.

secondly, what you have done there is created a closure on $x. that means that test2 when it is compiled creates a private copy of $x since that variable was lexical in an outer scope. put a print statement after the my $x line and you will see it never changes. only the private copy inside test2 gets increments.

making a anon sub would fix it if it was assigned in each call to test1. that would assign the value of $x each time test1 was called and the values would start from 0. making $x a global is an obvious but poor solution.

and finally when you print diagnostic output don't smush it together as that is not conducive to debugging

1. Perl does support nested sub routines. They help provide encapsulation to scoped variables. In other words, a variable declared with my will only be accessible through the sub routine nested in the same block, whereas the sub-routines can be called(and declared) from anywhere:

Code

{

my $x = 0;

sub test2 {

for (1..5) {

print ++$x;

}

print "\n";

}

}

test2(); # print '12345'

print $x, "\n"; # prints nothing, throws an error when using 'strict'

2. If you look closely at the output of the code you give, you will see that the second call to test1 IS working, but the output is '678910'. That is because test2 is accessing a private copy of $x which otherwise goes out of scope after the first call to 'test2'(via 'test1'). Initialize $x to '0' in the 'test2' sub and you will get the results you seem to want.

3. Try calling 'test2' with arguments(add the appropriate code to 'test2') and you will also get the results you seem to want. Doing this, 'test2' will be using the same private copy of $x that 'test1' is using, so when $x initializes $x to '0', 'test2' sees the re-initialization:

that is not a nested sub. that is a named sub scoped in a block which is a well known thing to do for creating the equivilent of c static variables. that is NOT what i was referring to. in perl declaring a named sub does not hide the sub name (unlike algol and PL/I). as i said, the OP accidentally created a closure there which was not his intention. there is no benefit to declaring a sub inside a sub in perl. just declaring both subs in an outer block with my $x in that block will do what he wants without being cluttered.

and there is ongoing debate in some perl circles as to whether this is a closure

Code

{ my $foo ;

sub next_foo { return ++$foo ; } }

some say that a closure is only created with anon subs since the copies of the closure variables need to be made and bound to the code reference. others claim the above code is also a closure since it does the same thing if only 1 time due to the named sub being used.