【问题标题】:How do I detect the 'strict' pragma within a module?如何检测模块中的“严格”编译指示?
【发布时间】:2014-08-15 04:48:00
【问题描述】:

通常,当我在 Perl 中构建数据结构时,我最终不得不将它从 %leaf 声明为 %root,所以我一直在修改一个允许我从
@987654324 构建的模块@到$seed->trunk->branch->leaf

AUTOLOADnew 子例程并不难。我对 SO 的问题是如何检测是否正在使用“严格”编译指示,以便模块以不同的模式运行,这需要在使用前“声明”变量,这样我就不会意外地为$seed->drunk 当我使用 strict 时——假设模块被称为 branch,这是模块使用的有效语法

$seed->declare('trunk');
$seed->trunk(new branch);

$seed->trunk->declare('leaf');
$seed->trunk->leaf("value");

如何检测严格的编译指示是否在模块的调用程序中生效?

这可能是不可能的——在这种情况下,我必须使用静态变量来处理与模块无关的编译指示。

编辑/后记:

我编写了不检查“严格性”或不实现“声明”子例程的初始版本,并意识到如果自动加载器通过引用操作,它不会提供足够简单的用户语法,所以我写它来检查对于第一个参数并将传递的值分配给对象引用的哈希表中的元素,否则如果没有参数,它将返回指定元素的值。

所以我发布分支模块的代码以满足您的好奇心。请注意,我还没有实施严格性检查。

package branch;

sub new
{
    my $type = shift;
    my $self = { };
    bless $self, $type;
    return $self;
}

sub DESTROY
{
    my $self = shift;
    %$self = undef;
}

sub AUTOLOAD
{
    my $self = shift;
    my $value = shift;

    my $sub = $AUTOLOAD;
    my ($type, $PROGRAM) = ($sub =~ /(.*)::(.*)/);

    if( $value ne undef )
    {
        $$self{$PROGRAM} = $value;
        return $value;
    }
    return $$self{$PROGRAM};
}

1;

【问题讨论】:

  • 检测它是否在哪里生效?限制不是全球性的。
  • 您的问题似乎缺少一些重要的上下文,并且使用了术语。您提到声明变量,但 $seed->trunk 是一个方法调用。 (显然它返回一个左值,否则您将无法分配给它。)我 认为 1)您将数据结构包装在 OO 接口中,2)您正在使用AUTOLOAD 自动生成访问器,以及 3) 您希望阻止 AUTOLOAD 为尚未预先声明的属性创建访问器。对吗?
  • 那有什么问题?我描述了我这样做的理由,并且我已经找到了我需要的答案。
  • @JustKevin:我只是想澄清一下。不清楚的问题很难回答,也不太可能对可能遇到类似问题的其他人有用。 (帮助所有人——不仅仅是原始海报——是 SO 的目的。)我还试图弄清楚这是否是 XY problem
  • @JustKevin 你是个混蛋。尽量不要成为一个家伙。

标签: perl perl-module


【解决方案1】:

嗯,第一件事是,严格的什么? Strict 有三个 subpragma,有它们自己的行为和要检查的位。 use strict 'refs' 不允许您取消引用字符串; use strict 'vars' 不允许您以非限定方式访问全局变量,use strict 'subs' 在少数情况之外禁用裸字。 use strict 等同于所有三个,但它们中的任何一个似乎都没有真正接近你所要求的值得捎带的东西。

所以要直接回答你的问题:caller($i) 返回的列表中的元素[8] 返回对$ith 级别调用者有效的编译提示位。如果您查看strict.pm,您可以看到每个 subpragma 设置的位,并在与实际调用您的方法的代码对应的调用者级别检查它们。

但是,回到我原来的观点,您可能不应该这样做,因为这不是严格的意义所在。您应该在对象的构造函数上接受一个选项,该选项决定它们是否应该严格执行,或者如果您真的想要一个词法编译指示而不是跟随您的对象的东西,您应该编写自己的使用perlpragma 中的信息作为教程。自 5.10 起的所有 perls 都支持使用 %^H 提示哈希的任意用户定义的编译指示,该哈希显示为调用者信息的元素 [10]

【讨论】:

  • 重点是我希望我实例化的对象从调用程序继承“严格性”并相应地表现;由于 AUTOLOAD 例程负责处理数据存储,该程序包绕过了 strict 'vars' 我认为这正是我需要的答案。
【解决方案2】:

您似乎对严格 pragma 的范围感到困惑。

如果模块使用严格,这不会对模块的用户强制执行任何操作。即使您想扩展包,也可以通过附加方法中的子类化或猴子补丁来扩展。

use strict 仅适用于它所在的文件。 (或者如果它在一对花括号中使用,它只适用于右大括号。)因此,如果您要扩展一个包,只需在一个单独的文件中进行,原始模块中应用的任何编译指示都不会适用于您的代码。


也就是说, use strict 并不是一个好主意。偶尔有一些任务在小范围内禁用它可能很有用,但您描述的问题似乎不是其中之一。

特别是,如果您正在构建一个深度嵌套的结构,则不需要声明每个级别。示范:

use strict;
use warnings;
use Data::Dumper;

my $root;
$root->{trunk}{branch}{leaf} = 42;

print Dumper($root);

【讨论】:

  • 我认为你错过了 OP 想要做的事情。如果调用他的模块的代码具有严格的效力,他希望他自己的模块遵守“严格”(他定义)的语义。
猜你喜欢
  • 2010-10-18
  • 2021-06-20
  • 2013-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-21
  • 2011-09-23
相关资源
最近更新 更多