【问题标题】:How can I import Perl code from external files at compile time?如何在编译时从外部文件导入 Perl 代码?
【发布时间】:2010-02-17 16:21:09
【问题描述】:

帮助佩勒斯!有谁知道一个简单的“在此处插入代码”方法会在编译时将外部文件中的代码一次带入包中?

背景:

我有一个标准的 PBP 风格的由内而外的类,它变得非常大。我想将代码拆分为多个文件,但不扩展类。最理想的情况是,我只需在编译时将代码插入示例模块的“Magic JuJu”部分(见下文)。

我已将 AutoLoader 视为完成此任务的一种手段。但是,有两件事让我停下来。如果我能解决这些问题,它可能是一个近乎最佳的解决方案:

  1. 我不想将每个小子拆分成一个单独的文件;只是一些更合理大小的文件(尽管在调用者中使用子存根很好);和

  2. 我不想在每个子节点上都推迟编译;我想在初次使用时编译一些潜艇。但是,这可能不会破坏交易。

我知道 Moose 提供了“角色”,我相信它做得很好,但由于各种原因,Moose 不是这个项目的一个选项,Moose 也不是。

我在“Magic JuJu”位置使用了“require q(some/file)”,但这并不能保持持久变量范围,即来自外部文件的子不会“看到”正确的对象属性散列(换句话说,将 require 放在文件的顶部会产生相同的效果)。我可以通过始终使用 setter 和 getter 来解决这个问题。所以这不是一个交易破坏者,但需要一些我不想承担的编码时间和执行开销。

最后,我不想扩展类;它已经具有多重继承。我只想要一个简单的“在此处插入代码”方法会在编译时将代码引入一次。

总结:

  1. (必需)将代码从外部文件导入包命名空间
  2. (必需)仅在编译时或最小运行时开销时这样做
  3. (必需)不扩展类
  4. (期望)荣誉插入位置范围

下面带有“Magic JuJu”注释的示例代码:

package T;

use strict;
use warnings;

########## BEGIN object persistent variables scope block ############
{
  my %Attr_Name_Env;

  ## Constructor 'new'
  #
  sub new {
    ## Get and confirm arguments
    #
    my $class      = shift;
    my $href_arg = {@_};
    my $name_env = $href_arg->{'name_env'};

    ## Bless anon scalar into class
    #
    my $obj_new   = bless anon_scalar(), $class;
    my $idx_self  = ident $obj_new;

    # Populate object attributes
    #
    $Attr_Name_Env{ $idx_self } = $name_env;

    return $obj_new;
  }
  ## END Constructor 'new'

  sub DESTROY {... as you do ...}

  sub t_get_name_env {
    my $self      = shift;
    my $idx_self  = ident $self;
    return $Attr_Name_Env{ $idx_self };
  }

  ## insert magic juju here

}
########## END object persistent variables scope block ############

1;

也许是一个带有 slurp 和 eval 的 BEGIN 块......

【问题讨论】:

  • 你为什么关心班级人数?

标签: perl perl-module


【解决方案1】:

您可以只使用模块并导入所需的潜艇。

use MyMod qw( wanted_sub_1 wanted_sub2 );

要访问您的属性哈希,您需要为您的目标模块修改import

package MyClass;
use MyMod { attrib1 => \%attrib1, attrib2 => \%attrib2 }, qw( wanted_sub1 wanted_sub2 );

MyModimport 然后会创建封闭在初始哈希参数上的代码引用,并将它们安装到MyClass 命名空间中。

【讨论】:

  • 1.这些属性通过包含块在词法范围内限定,因此除非删除该包含块,否则它们对 MyMod 不可用。这会使属性不是真正私有的,但这可能没问题。或者可以只对属性使用访问器。 2. MyMods subs 会想要使用类中的方法,尤其是继承的方法。我认为这将适用于标准的my $self = shift 方法,但需要进行测试。 3. 有点冗长,但也许是最正确的。会回来汇报的。越读越害怕源过滤器
  • 我用这个方法让它工作了!导入方法对于一般的开发者来说有点迟钝,而且有点冗长。但它很干净而且很有效,而且肯定非常糟糕。此外, perl -cw 适用于每个模块,非常好。 Filter::Macro 无法工作,对于这个应用程序来说看起来有点太神奇了。
  • 顺便说一句,要查看实际工作代码,请转到此处:perlmonks.org/?node_id=823764
  • 感谢您发布代码。只是给出一个大纲我感觉很糟糕,但我感冒了,老脑子没有勇气为你制作它。自定义导入例程让你做各种魔术。他们可以很有趣。
【解决方案2】:

如果你愿意承担后果,有Filter::Macro

【讨论】:

  • 不,不是过滤器!恐怖,恐怖!
  • 嗨思南!谢谢! Filter::Macro 看起来确实是个不错的选择。你在上面提到了后果。你能和我分享一下那些可能是什么吗?
  • @Michael:您将使用源过滤器。 ;-) Filter::Macro 很简单,我认为这不会成为问题,但源过滤器往往有点脆弱,我不知道Filter::Macro 是否可以安全地与其他所有模块一起使用。
  • 感谢思南!我目前正在检查上面的方法,但可能会返回Filter::Macro。
猜你喜欢
  • 1970-01-01
  • 2013-01-23
  • 1970-01-01
  • 2015-12-21
  • 1970-01-01
  • 2010-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多