Un hack est nécessaire car require(et donc use) à la fois compile et exécute le module avant de revenir.
Il en va de même eval. evalne peut pas être utilisé pour compiler du code sans l'exécuter également.
La solution la moins intrusive que j'ai trouvée serait de passer outre DB::postponed. Ceci est appelé avant d'évaluer un fichier requis compilé. Malheureusement, il n'est appelé que lors du débogage ( perl -d).
Une autre solution serait de lire le fichier, de le modifier et d'évaluer le fichier modifié, un peu comme ce qui suit:
use File::Slurper qw( read_binary );
eval(read_binary("Foo.pm") . <<'__EOS__') or die $@;
package Foo {
no warnings qw( redefine );
sub bar { 7 }
}
__EOS__
Ce qui précède n'est pas correctement défini %INC, il gâche le nom de fichier utilisé par les avertissements et autres, il n'appelle pas DB::postponed, etc. La solution suivante est plus robuste:
use IO::Unread qw( unread );
use Path::Class qw( dir );
BEGIN {
my $preamble = '
UNITCHECK {
no warnings qw( redefine );
*Foo::bar = sub { 7 };
}
';
my @libs = @INC;
unshift @INC, sub {
my (undef, $fn) = @_;
return undef if $_[1] ne 'Foo.pm';
for my $qfn (map dir($_)->file($fn), @libs) {
open(my $fh, '<', $qfn)
or do {
next if $!{ENOENT};
die $!;
};
unread $fh, "$preamble\n#line 1 $qfn\n";
return $fh;
}
return undef;
};
}
use Foo;
J'ai utilisé UNITCHECK(qui est appelé après la compilation mais avant l'exécution) parce que j'ai ajouté le remplacement (à l'aide unread) plutôt que de lire le fichier entier et d'ajouter la nouvelle définition. Si vous souhaitez utiliser cette approche, vous pouvez obtenir un descripteur de fichier à retourner en utilisant
open(my $fh_for_perl, '<', \$modified_code);
return $fh_for_perl;
Félicitations à @Grinnz pour avoir mentionné les @INCcrochets.
Foo::bar, maisuse Fooelle exécutera à la fois la phase de compilation (barre de redéfinition si quelque chose a déjà été définie là-bas) et la phase d'exécution de Foo. La seule chose à laquelle je peux penser serait un@INCcrochet profondément hacky pour modifier la façon dont Foo est chargé.