如何在编译时从外部文件导入 Perl 代码?

发布于 2024-08-22 10:26:46 字数 1793 浏览 7 评论 0原文

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

背景:

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

我将 AutoLoader 视为实现这一目标的一种手段。然而,有两件事让我犹豫不决。如果我可以解决这些问题,这可能是一个近乎最佳的解决方案:

  1. 我不想将每个小子文件拆分为一个单独的文件;只是一些大小更合理的文件(不过,在调用者中使用子存根就可以了);而且

  2. 我不想推迟每个子项目的编译;我想在初次使用时编译一些潜艇。然而,这可能不会破坏交易。

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

我在“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 块......

Help Perlers! Does anyone know a simple "insert code here" approach would bring code from external files once at compile time into a package?

Background:

I have a standard PBP-style inside-out class that is getting quite large. I want to split the code into multiple files but not extend the class. Optimally, I would simply insert the code into the "Magic JuJu" section of the example module (see below) once at compile time.

I have looked at AutoLoader as a means to get this accomplished. However, there are two things that give me pause. If I could get around these, it might be a near-optimal solution:

  1. I don't want to split every little sub into a separate file; just a few more reasonably sized files (using sub stubs in the caller is fine, though); and

  2. I don't want to defer compile on every sub; some subs I'd like to have compiled on initial use. However, this is probably not a deal breaker.

I know Moose provides "Roles", which I believe does this well, but for various reasons, Moose is not an option for this project, nor is Mouse.

I have used "require q(some/file)" in the "Magic JuJu" location, but that does not maintain the persistent variable scope, i.e. subs from the external file don't "see" the object attribute hashes correctly (in still other words, putting the require at the top of the file would have the same effect). I could get around that by always using setters and getters. So that is not a deal breaker, but would require a bit of coding time and execution overhead that I'd rather not incur.

Finally, I don't want to extend the class; it already has multiple inheritance. I just want a simple "insert code here" approach would bring the code in once at compile time.

In summary:

  1. (Required) imports code from external files into package namespace
  2. (Required) Does so only at compile-time or minimal run-time overhead
  3. (Required) Does not extend class
  4. (Desired) Honors insert location scope

Example Code with "Magic JuJu" comment below:

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;

Maybe a BEGIN block with a slurp and eval ...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不醒的梦 2024-08-29 10:26:46

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

use MyMod qw( wanted_sub_1 wanted_sub2 );

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

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

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

You could just use the modules and import the desired subs.

use MyMod qw( wanted_sub_1 wanted_sub2 );

To get access to your attribute hashes you will need to modify import for your target modules.

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

MyMod's import would then create code refs that are closed over the initial hash argument, and install those into the MyClass namespace.

葬﹪忆之殇 2024-08-29 10:26:46

如果您愿意承担后果,可以使用 Filter::Macro

If you are willing to live with the consequences, there is Filter::Macro.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文