in reply to Making lexically-scoped ref available to non-OO subs in another package

This seems to work fine for me:

#!/usr/bin/env perl use v5.14; package The::Package { use Carp; use base "Exporter"; BEGIN { our @EXPORT = qw( my_generator foo takes_coderef ) }; my $scratchpad; sub my_generator (&) { $scratchpad = {}; shift->(); my $tmp = $scratchpad; undef $scratchpad; return $tmp; } sub foo ($) { croak "foo must be called within my_generator" unless $scratch +pad; $scratchpad->{foo} = shift; } sub takes_coderef (&) { croak "takes_coderef must be called within my_generator" unles +s $scratchpad; $scratchpad->{coderef} = shift; } BEGIN { $INC{"The/Package.pm"} = __FILE__ }; }; use The::Package; use Data::Dumper; my $complex_result = my_generator { foo 'bar'; takes_coderef { ... }; }; print Dumper($complex_result); foo 'baz'; # Should not affect $complex_result. # Ideally, should croak, or not even compile.

If you want to be able to nest calls to my_generator then you need to have a stack of scratchpads, but that's very little extra work.

package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name

Replies are listed 'Best First'.
Re^2: Making lexically-scoped ref available to non-OO subs in another package
by wanna_code_perl (Friar) on Jul 12, 2013 at 13:30 UTC
    package The::Package { use Carp; use base "Exporter"; BEGIN { our @EXPORT = qw( my_generator foo takes_coderef ) }; my $scratchpad; sub my_generator (&) { $scratchpad = {}; shift->(); my $tmp = $scratchpad; undef $scratchpad; return $tmp; }

    Just when I thought I was getting the hang of Perl..! I had no idea a my package variable would work like this.

    I'm amazed at the elegance of this, and that you came up with this rather instantaneously. Thank you!

      I probably wouldn't have come up with it so quickly if I hadn't been playing around with p5-mop-redux which is a prototype of a hopefully future Perl core feature. The prototype uses rather a similar technique (combined with lots of Devel::Declare magic) to provide its class-building syntax, though it uses localized package variables rather than lexicals.

      (I've also done something fairly similar in Smart::Dispatch.)

      package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name