Bir kesmek gereklidir çünkü require(ve böylece use) her iki derlenir ve yürütür modülü dönmeden önce.
Aynı şey geçerli eval. evalkodu yürütmeden de derlemek için kullanılamaz.
Bulduğum en az müdahaleci çözüm geçersiz kılmak olurdu DB::postponed. Bu derlenmiş gerekli bir dosyayı değerlendirmeden önce çağrılır. Ne yazık ki, yalnızca hata ayıklama ( perl -d) sırasında çağrılır .
Başka bir çözüm, dosyayı okumak, değiştirmek ve değiştirilmiş dosyayı değerlendirmek olabilir, örneğin aşağıdakiler gibi:
use File::Slurper qw( read_binary );
eval(read_binary("Foo.pm") . <<'__EOS__') or die $@;
package Foo {
no warnings qw( redefine );
sub bar { 7 }
}
__EOS__
Yukarıdakiler düzgün ayarlanmamıştır %INC, uyarılar tarafından kullanılan dosya adını karıştırır ve böyle çağırmaz DB::postponed, vb. Aşağıdakiler daha sağlam bir çözümdür:
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;
Ben kullandım UNITCHECK(derleme sonra ama yürütmeden önce denir) çünkü unreadtüm dosyayı okumak ve yeni tanım eklemek yerine geçersiz kılma (kullanarak ) önermiş. Bu yaklaşımı kullanmak istiyorsanız, kullanarak geri dönmek için bir dosya tanıtıcısı alabilirsiniz
open(my $fh_for_perl, '<', \$modified_code);
return $fh_for_perl;
Horoz bahsettiği için @Grinnz için Kudos @INC.
Foo::bar, ancakuse Foohem derleme aşamasını (daha önce tanımlanmış bir şey varsa yeniden tanımlama çubuğu) hem de Foo'nun çalışma zamanı aşamasını çalıştıracaktır. Aklıma gelen tek şey,@INCFoo'nun nasıl yüklendiğini değiştirmek için derin bir çengel kanca olurdu .