in reply to Inner subroutines?

The "inner" sub is actually visible to everyone.

$ perl -wE'sub o { sub i { say "foo"; } } i();' foo

The "inner" sub cannot use variables from the "outer" sub.

$ perl -wE'sub o { my ($x) = @_; sub i { say $x; } i(); } o("abc"); o( +"def");' Variable "$x" will not stay shared at -e line 1. abc abc

I tend to call what you have a bug, not a technique.

Replies are listed 'Best First'.
Re^2: Inner subroutines?
by bart (Canon) on Feb 11, 2011 at 16:28 UTC
    It's one of my major peeves with Perl5: that inner subs don't work it is as reasonable to expect. The way they work in Javascript, for example.

    It's the reason why you cannot use "my" variables in the top level of source files for mod_perl, when using Apache::Registry, the easy route from CGI to mod_perl.

    There are articles on how to fix variables for inner subroutines, but the fact that you even need to worry about it is a major counterpoint against Perl, in my opinion.

    The reason, as far as I gather, is because BEGIN (and related) blocks are actually subs, that are executed once; you can even use the syntax

    sub BEGIN { ... }
    and subs defined in BEGIN blocks are global subs.

    And, Larry Wall and other prominent figures have said, years ago, that it'll never be "fixed". Because it is so by design.

      It's got nothing to do with BEGIN being sub-like. Inner subs would have to capture every time the outer sub is called. But since there are no private subs in Perl, there isn't necessarily any executing outer sub to capture from.

      sub outer { sub inner { } }
      is basically
      sub outer { BEGIN { *inner = sub { }; } }
      Replace it with
      sub outer { *inner = sub { }; }

      and inner will capture properly for an inner sub. Of course, problems will still ensue if you call inner() from outside of outer(). To solve that, you'd need a language feature such as

      sub outer { my sub inner { } }