【问题标题】:How can I write code that optionally uses a module if it exists? [duplicate]如果模块存在,我如何编写可以选择使用模块的代码? [复制]
【发布时间】:2021-03-03 05:59:56
【问题描述】:

如果我想编写可选地使用模块的代码,我该怎么做?例如,如果我想编写 warns 转储对象的代码,如果 Data::Dumper 可用,或者只有 warns,我该怎么做?

【问题讨论】:

  • 这个问题不应该作为重复而关闭,因为这个问题有两个部分。 1. 如何选择性地加载模块 2. 如何选择性地使用子程序。
  • #2 的答案是这样的。 use constant haveDumper => defined &Dumper; sub warning { haveDumper ? warn(Dumper @_) : warn(@_); } 检查子程序是否可用的一般方法是defined &NAME。这很重要,因为子程序可以由各种模块提供。如果您需要检查自动加载的子例程,请使用exists &NAME

标签: perl module require


【解决方案1】:
BEGIN {
   if (eval { require Data::Dumper }) {
      *dumper = sub { warn(Data::Dumper::Dumper(@_)) };
   } else {
      *dumper = sub { };
   }
}

dumper(...);

上述方法的缺点是,如果 Data::Dumper 不可用,作为参数传递的昂贵表达式仍然需要计算。

use constant has_dumper => eval { require Data::Dumper };

BEGIN {
   if (has_dump) {
      *dumper = sub { warn(Data::Dumper::Dumper(@_)) };
   } else {
      *dumper = sub { };
   }
}

dumper(...);                # Ok
dumper(...) if has_dumper;  # Statement completely optimized away if DD missing.

【讨论】:

    【解决方案2】:

    这是加载可选模块的有效习惯用法,

    use constant has_Module => defined eval { require Module };
    

    这将需要模块(如果可用),并将状态存储在常量中。

    你可以这样使用,

    use constant has_DataDumper => defined eval { require Data::Dumper };
    
    warn "got object";
    if ( has_DataDumper ) {
      warn Data::Dumper::Dumper( $obj );
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-29
      • 1970-01-01
      • 1970-01-01
      • 2021-12-05
      • 2017-06-04
      相关资源
      最近更新 更多