develooper Front page | perl.perl5.porters | Postings from April 2007

idea for yet another LNV and caller() return value (was: The Strict trap)

Thread Next
From:
David Nicol
Date:
April 25, 2007 09:20
Subject:
idea for yet another LNV and caller() return value (was: The Strict trap)
Message ID:
934f64a20704250919x69b5d1dm644b1197ae10787c@mail.gmail.com
On 4/25/07, Johan Vromans <jvromans@squirrel.nl> wrote:
> > What solution would you suggest ?
>
> No attempt is
> made to provide a more generic solution for pragmata in general since
> these solutions seems to be too risky.

this is more of a follow-up on my own suggestion yesterday that C<use>
within a scope could imply C<no> on scope exit than a comment directly
on the matter at hand.

I know that Perl maintains a list of things to do on scope exit, which is
where C<local>ized variables get reassigned to their original values, and
possibly other things as well.  How tricky would it be to provide perl-side
access to that list, in the form of, say @^TTD_ON_SCOPE_EXIT,
or in the form of a twelfth result from C<caller> -- although caller works
at the granularity of stack frames rather than scopes, so something similar
that works with lexical scopes, and enclosers of lexical scopes, would make
more sense.  C<encloser> perhaps?

To implement implied C<no> using this proposed mechanism, one would
push or unshift C<sub { no __PACKAGE__ }> onto that list, using a
constructed L-value of something like

     package lexical_foo;
     use Devel::encloser;   #made up

     sub import{
             my $caller = caller();  # package name
             my $old_foo = \&{$caller.'::foo'};
             *{$caller.'::foo'} = \&foo;
             unshift @{encloser(1)->[ENCLOSER_TTD_ONCLOSE]}, sub {
                    \&{$caller.'::foo'} = $old_foo
             };
     };

hmm.  Invoking C<no> would make things more complex because convenient
closures could no longer be used -- or could they?


     package lexical_foo;
     use Devel::encloser;   #made up

     sub import{
             my $caller = caller();  # package name
             push @{$caller."::foo_old_foo"}, \&{$caller.'::foo'};
             *{$caller.'::foo'} = \&foo;
             unshift @{encloser(1)->[ENCLOSER_TTD_ONCLOSE]}, 'no foo';
     };

     sub unimport{
             my $caller = caller();  # package name
             *{$caller."::foo"} = pop @{$caller.'::foo_old_foo'};
    };

The implied scope around C<use> would need to be dealt with correctly, which
either means (1) removing it somehow or (2) Devel::encloser would have a way
to skip it when its there or (3) we document the implied scope around C<use>
as something that is not going to go away, and provide working examples
manipulating the do-on-scope-close list two scopes up instead of one.

Could the list of enclosing scopes, in the form of some kind of manipulable
perl objects, be provided as an additional return value from C<caller>?


i know I am oversimplifying lots and lots of things here and no I
have no time scheduled for implementing any of this at the moment.

And I have not fully examined the available B and Devel packages to
determine if the functionality I am describing is not there already.  I think
that if it were there, people would refer to it whenever the subject of
lexical pragmata comes up.

Although lexical isn't really the deal here -- we have user-manipulable %^H for
that -- a module that its importation has the same footprint as a localized
variable change is what I'm aiming towards, by exposing the mechanism by
which C<local> resets stuff.

Currently to the best of my knowledge (somebody please enlighten me in the
event that I am mistaken on this) the best way to mock up a
do-this-on-scope-exit
involves tieing something to a local variable and coattailing the reset action
directly.  A similar approach which runs the risk of failing in the
far future when
Perl drops refcounting for a nondeterministic garbage collection is associating
code with a tied lexical and using the DESTROY hook.  And there is
no way to directly add a coderef to the scope exit to do list that is
not a hack, and
no simple way at all to add a coderef to the scope exit to do list of
an enclosing
scope:  mechanisms based on C<local> or on lexical destruction can only operate
at the current scope, and have no advantage over unifying a functions
exit points
and simply running the code at the bottom.

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About