【问题标题】:Perl library to avoid redefining an already defined functionPerl 库以避免重新定义已定义的函数
【发布时间】:2011-08-18 21:50:57
【问题描述】:

我有两个 perl 模块文件,例如:

is_date_holiday.pl:

use strict;
use warnings;
sub IsDateHoliday
{
   ...
}
1

calc_prev_working_date_mult.pl:

use strict;
use warnings;
require "is_date_holiday.pl"; # IsDateHoliday
sub CalcPrevWorkingDateMult 
{
   ...
}
1

在 perl 文件中同时使用它们,例如:

require "is_date_holiday.pl"; # IsDateHoliday
require "calc_prev_working_date_mult.pl" # CalcPrevWorkingDateMult

它抱怨我正在重新定义函数 IsDateHoliday

如何做相当于 #ifndef 的?

【问题讨论】:

  • 你拥有的不是模块!
  • %INC 机制(参见perldoc -f require)已经采取措施阻止文件被加载两次。您发布的代码与实际运行的代码相同吗?你确定你没有在一个地方做类似require "file.pl" 而在另一个地方做require "./file.pl" 的事情吗? require "File.pl" 和 require "file.pl" 在不区分大小写的系统上?或者&IsDateHoliday 没有在其他地方定义?
  • @mob,我注意到这个解释有些可疑,但无论如何解决方法都是一样的。

标签: perl module


【解决方案1】:

您实际上没有modules,但您应该拥有。

IsDateHoliday.pm:

package IsDateHoliday;

use strict;
use warnings;

use Exporter qw( import );
our @EXPORT_OK = qw( IsDateHoliday );
our %EXPORT_TAGS = ( all => \@EXPORT_OK );

sub IsDateHoliday
{
   ...
}

1;

CalcPrevWorkingDateMult.pm:

package CalcPrevWorkingDateMult;

use strict;
use warnings;

use Exporter qw( import );
our @EXPORT_OK = qw( CalcPrevWorkingDateMult );
our %EXPORT_TAGS = ( all => \@EXPORT_OK );

use IsDateHoliday qw( :all );

sub CalcPrevWorkingDateMult
{
   ...
}

1;

main.pl:

use IsDateHoliday           qw( :all );
use CalcPrevWorkingDateMult qw( :all );

【讨论】:

  • 应将:all 替换为您要导入的函数的名称。
  • 修正了“Exporter”的拼写。
【解决方案2】:

你真的应该为这些创建包,然后use 他们。这将消除重新定义的问题,因为您可以导入您需要的内容,use 不会导入两次。

package IsDateHoliday;
use strict;
use warnings;
use Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(IsDateHoliday);

sub IsDateHoliday {
 #...
}

1; # not a typo, Perl needs modules to return true

将文件命名为“IsDateHoliday.pm”,然后在需要时使用:

use strict;
use lib '.'; # to include the local directory
use IsDateHoliday;

对另一个进行同样的处理。

当然,有人可能会质疑为什么您不只使用 CPAN 中的Date::Calc。 (可能没有假期,但我敢肯定 CPAN 上还有其他事情!)

【讨论】:

    【解决方案3】:

    虽然最好改为use 而不是require,这将首先检查它是否已经被加载,如果你真的想用perl 编写C,很可能最接近您尝试做的就是设置一些变量,并检查是否存在,但您必须将子例程定义隐藏在eval 中。 # 在包含的文件中: 我的 $DateHolidayLoaded;

    if ( !$DateHolidayLoaded ) {
        eval {
            sub IsDateHoliday { ... }
            $DateHolidayLoaded = 1;
        };
    }
    

    你也可以测试一个函数是否存在,但是你必须指定要使用的命名空间......在这种情况下,它应该是'main':

    if ( ! defined( main->can( 'IsDateHoliday' ) ) ) { require 'is_date_holiday.pl' }
    

    但这仅适用于执行包含的文件;如果您在包含子例程定义的文件中进行此测试,则始终为 true。

    【讨论】:

    • eval 代码已完全损坏。 eval BLOCK 无法捕获在运行之前发生的错误,并且它不会使警告静音(这是 OP 正在接收的)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-05
    • 1970-01-01
    • 2010-10-13
    • 2012-03-08
    相关资源
    最近更新 更多