5

私は次のコードを持っています:

#!/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マシンにプラグマがあり(を使用して完全にロード可能use)、なぜ正常にrequire機能しないのか疑問に思いました(指数関数的な数値を取得しています。 "大きな数字」)この場合は?

ありがとう、

4

3 に答える 3

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;
} 
于 2012-07-25T17:29:40.803 に答える
2
BEGIN {
   require bignum;
   import bignum;
   my $x = 1;
}

require bignum;
import bignum;
my $x = 1;

とはすでにコンパイルされた後に実行されるためrequire、同じです。したがって、bignumはコンパイルをに行う機会がありません。それを念頭に置いてimportmy $x = 1;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;
}
于 2012-07-25T20:21:55.613 に答える
0

他の多くのプラグマと同様に、新しいバージョンのPerlでは、bignumインポートしたスコープでのみアクティブになります。ただし、多くの場合とは異なり、スコープ番号をアップグレードすると、ファンキーな混乱が発生します。これは、だけではうまく機能しませんrequire。スコープを分離し、それでも魔法を実行させるには、その存在を確認し、2つの異なるファイルで使用する必要があります。

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;
于 2012-07-25T17:24:59.513 に答える