Like already explained, it's the delete of the typeglob aka symbol which is causing the problem,
This works for me
use lib '.'; use My; eval "My::Run('eval')"; My::Run('normal'); delete $INC{"My.pm"}; # --- Why do this? undef &My::Run; # 1. Avoids warning redefined # 2. will deactivate function if missing in new module # --- Why DON'T do this # delete $My::{Run}; # If you destroy the symbol, Perl won't know how to handle optimies op +code require My; eval "My::Run('eval')"; My::Run('normal');
---- Loading My at 1727478470.8689 ... Running Run(eval) loaded at 1727478470.8689 Running Run(normal) loaded at 1727478470.8689 ---- Loading My at 1727478470.87299 ... Running Run(eval) loaded at 1727478470.87299 Running Run(normal) loaded at 1727478470.87299
IMHO both, normal call and eval should work. Also importing symbols.
The following solution seems to work and should probably be a module on CPAN.
Basic idea is to never use use from the beginning. I.e. don't load at compile time. Use runtime "reuse" at the beginning of execution.
Like that the calls in the OP-Code will never optimize to refs and hence always check the symbols in the STASH, without weird side-effects.
use v5.12; use warnings; use lib "."; ReUse::reuse("My" => 1,2,3); My::Run("normal"); eval 'My::Run("eval")'; ReUse::reuse("My" => 1,2,3); My::Run("normal"); eval 'My::Run("eval")'; package Test; my $data = [1..5]; say "\n\n---- ReImporting from module"; ReUse::reuse("Data::Dump" => qw/pp/); pp($data); # test import say "\n\n---- ReImporting from module"; ReUse::reuse("Data::Dump" => qw/pp/); pp($data); # test import exit; # --- this should probably be a proper CPAN Module package ReUse; sub reuse { my ($module, @imports) = @_; # --- purge %INC my $inc_key = "$module.pm"; $inc_key =~ s(::)(/)g; my $oldpath = delete $INC{$inc_key}; # --- build code # --- require at runtime my $PACKAGE = (caller)[0]; my $REQUIRE = $inc_key; eval <<"__CODE__"; package $PACKAGE; require "$REQUIRE"; __CODE__ if ($@) { die qq(REQUIRE of "$module" failed with: <$@>); } # --- import at runtime my $IMPORTS = join ",", map {"'$_'"} @imports; eval <<"__CODE__"; package $PACKAGE; $module->import($IMPORTS); __CODE__ if ($@) { die qq(IMPORT OF "$module->import($IMPORTS)" failed with: <$@> +); } # --- warn if module's path changed # TODO make optional if ($oldpath and $oldpath ne $INC{$inc_key}) { # untested TODO warn "Path of $module changed"; } }
---- Loading My at 1727477140.49975 ... Running Run(normal) loaded at 1727477140.49975 Running Run(eval) loaded at 1727477140.49975 ---- Loading My at 1727477140.50415 ... Running Run(normal) loaded at 1727477140.50415 Running Run(eval) loaded at 1727477140.50415 ---- ReImporting from module [1 .. 5] ---- ReImporting from module [1 .. 5]
NB: I didn't bother to purge the old STASH with the old symbols to have a clean start, because:
Last but not least: my My.pm (put in the same dir like above code).
package My; use v5.12; use warnings; no warnings "redefine"; use Time::HiRes qw(time); my $loadtime = time(); say "\n\n---- Loading " . __PACKAGE__ . " at $loadtime ... "; sub Run { say "Running Run(@_) loaded at $loadtime" }
HTH
Cheers Rolf
(addicted to the Perl Programming Language :)
see Wikisyntax for the Monastery
In reply to Re: Refresh a Module
by LanX
in thread Refresh a Module
by Timka
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |