On Fri, May 02, 2014 at 06:21:04PM -0400, Victor Efimov via RT wrote:
Show quoted text> Fri May 02 18:21:03 2014: Request 95298 was acted upon.
> Transaction: Ticket created by vsespb
> Queue: namespace-clean
> Subject: cannot redefine subroutine by symbolic ref when namespace::clean
> is in use
> Broken in: 0.25
> Severity: Normal
> Owner: Nobody
> Requestors: victor@vsespb.ru
> Status: new
> Ticket <URL:
https://rt.cpan.org/Ticket/Display.html?id=95298 >
>
If we swap I.pm with Carp.pm, change 'mysub' with 'carp', and (roughly)
recreate the namespace::clean functionality, your example looks like
this one-liner:
perl -e '
use warnings;
use strict;
no warnings "redefine";
no strict "refs";
BEGIN { require Carp; *{"carp"} = \&Carp::carp }
carp("Foo");
*{"carp"} = sub { warn "not the carp you are looking for" };
carp("Bar");
BEGIN { delete ${*main::}{carp} }
'
Note the sequence of events:
0) the carp stash slot is created
1) the parsing of both carp(...) calls (not their execution)
2) the stash-slot is deleted
3) the first carp() is called
4) the stash gets a new member reintroduced
5) the second carp() is called
After steps 0 and 1 both the resulting optree entries AND
*{${*main::}{carp}}{CODE} are "aliases" to the same GlobSlot. This is
why in your non-n::c code you can change *{"carp"} and see the changes
reflected in the optree. However in the above case at step 2 this
aliasing is lost for good, and you are seeing the effect you are seeing.
I don't think there is much namespace::clean can do to make this easier
for your use case. I will keep this ticket open for another week to
facilitate further discussion (if any). Feel free to close this ticket
earlier if there isn't much to add.
Cheers