[英]perl 'require' in begin block
我有以下代碼:
#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';
BEGIN {
my $supported = undef;
*compute_factorial = sub { if (eval { require bignum; bignum->import(); 1;}) {
my $num = shift;
my $factorial = 1;
foreach my $num (1..$num) {
$factorial *= $num;
}
return $factorial;
} else {
undef;
} };
};
my $f = compute_factorial(25);
say $f;
我只是在測試某種東西,而不是真正的生產代碼……我的機器上確實有bignum
pragma(可以使用use
完全加載),我想知道為什么require
不能正常工作(我正在獲取指數數)而不是“大數字”)?
謝謝,
bignum的導入需要在要實現的代碼編譯之前被調用,否則將不起作用。 在這里,BEGIN使它在您實際的compute_factorial調用之前被調用,但在關鍵my $factorial = 1;
之前未調用my $factorial = 1;
被編譯。
對於這種情況,更好的方法是直接使用Math :: Big *:
if (eval { require Math::BigInt }) {
my $num = shift;
my $factorial = Math::BigInt->new(1);
foreach my $num (1..$num) {
$factorial *= $num;
}
return $factorial;
} else {
undef;
}
BEGIN {
require bignum;
import bignum;
my $x = 1;
}
和
require bignum;
import bignum;
my $x = 1;
是相同的,因為在my $x = 1;
之后執行了require
和import
my $x = 1;
已被編譯,因此bignum永遠沒有機會使my $x = 1;
編譯成my $x = Math::BigInt->new(1);
。 請記住
use bignum;
my $x = 1;
實際上是
BEGIN {
require bignum;
import bignum;
}
my $x = 1;
並不是
BEGIN {
require bignum;
import bignum;
my $x = 1;
}
解決方案是
BEGIN {
my $sub;
if (eval { require bignum; }) {
$sub = eval(<<'__EOI__') or die $@;
use bignum;
sub {
my ($num) = @_;
my $factorial = 1;
$factorial *= $_ for 2..$num;
return $factorial;
}
__EOI__
} else {
$sub = sub { croak "Unsupported" };
}
*factorial = $sub;
}
當然,由於您可以簡單地消除實用性,所以最好。
BEGIN {
my $sub;
if (eval { require Math::BigInt; }) {
require Math::BigInt;
$sub = sub {
my ($num) = @_;
my $factorial = Math::BigInt->new(1);
$factorial *= $_ for 2..$num;
return $factorial;
};
} else {
$sub = sub { croak "Unsupported" };
}
*factorial = $sub;
}
與許多其他編譯指示一樣,在較新版本的Perl bignum
它僅在導入它的作用域中處於活動狀態。 但是,與許多其他方法不同,它還與升級有作用域的數字做了一些時髦的混淆,而這僅與require
不能完全配合。 您將不得不中斷檢查它的存在,並在兩個不同的文件中使用以隔離作用域,並且仍然讓它發揮作用。
big.pl
if (eval { require bignum; 1 }) {
require big_loader;
}
print big_loader::big_num_returner();
print "still ok\n";
big_loader.pm
package big_loader;
use bignum;
sub big_num_returner {
return 2**512
}
1;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.