簡體   English   中英

perl'require'在開始塊

[英]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;之后執行了requireimport 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM