我有以下代码:
#!/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
不能正常工作(我得到指数而不是“在这种情况下大数字?)
谢谢,
答案 0 :(得分:3)
bignum的导入需要在编译要编译的代码之前调用,否则它不起作用。在这里,BEGIN在实际的compute_factorial调用之前调用它,但在编译关键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;
}
答案 1 :(得分:2)
BEGIN {
require bignum;
import bignum;
my $x = 1;
}
和
require bignum;
import bignum;
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;
}
答案 2 :(得分:0)
与许多其他编译指示一样,较新版本的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;