在@ISA 上使用拼接在 perl 5.12.2 中是不是存在问题?

Posted

技术标签:

【中文标题】在@ISA 上使用拼接在 perl 5.12.2 中是不是存在问题?【英文标题】:Is there a problem in perl 5.12.2 using splice on @ISA?在@ISA 上使用拼接在 perl 5.12.2 中是否存在问题? 【发布时间】:2011-04-26 01:03:17 【问题描述】:

以下是 Perl 5.12 上的调试会话。这有意义吗? UNIVERSAL 是否缓存 @ISA 变量的一个版本,如果永远使用它。在Class::ISA 被弃用之前,我曾经调用Class::ISA::self_and_super_path 来让内部重新查看@ISA 数组。既然现在被认为是不必要的,那么你如何让 perl 来审计它的内部记录呢?

DB<34> p $papa
Papushka=HASH(0x16bc0300)

DB<35> p $papa->isa('Nanushka')

DB<36> p $papa->isa('Babushka')
1

DB<37> x @Papushka::ISA
0  'Nanushka'
1  'Babushka'

这是测试代码(显然)。它得到相同的结果,运行平坦,作为测试运行,或在调试中运行。我应该告诉你,在此之前@ISA = qw&lt;Babushka&gt; 和我表演了

splice( @ISA, 0, 0, 'Nanushka' );

是这个问题吗?你应该只将push 转到@ISA 吗?

【问题讨论】:

【参考方案1】:

是的,有一个缓存。但是,如果您可以修改 @ISA 而不会使该缓存失效,我会认为它是 perl 中的错误。

如果在splice 行之后添加@ISA = @ISA; 行,您的问题会消失吗?

【讨论】:

一定会尝试@ISA=@ISA。除了它会更像@$isa_ref = @$isa_ref。在哪里$isa_ref = *Papushka::ISAARRAY【参考方案2】:

Class::ISA::self_and_super_path 的替换是 mro::get_linear_isa。这可以从 mro 本身获得,或者,如果你想支持旧的 perls,可以通过 MRO::Compat 获得。

另外,@ISA 是一个神奇的变量。

$ perl -MDevel::Peek -e'Dump \@ISA'
SV = IV(0x1b92e20) at 0x1b92e28
  REFCNT = 1
  FLAGS = (TEMP,ROK)
  RV = 0x1bbcd58
  SV = PVAV(0x1b93cf8) at 0x1bbcd58
    REFCNT = 2
    FLAGS = (SMG,RMG)
    MAGIC = 0x1bc0f68
      MG_VIRTUAL = &PL_vtbl_isa
      MG_TYPE = PERL_MAGIC_isa(I)
      MG_OBJ = 0x1bbcd40
    ARRAY = 0x0
    FILL = -1
    MAX = -1
    ARYLEN = 0x0
    FLAGS = (REAL)

注意PERL_MAGIC_isa。这就是驱动这种特殊机制的原因。

每当它被改变时,依赖于它的值的任何缓存的内容都应该被更新。

$ perl -E'say Foo->isa(q[Bar]) || 0; @Foo::ISA = qw(Bar Baz); say Foo->isa(q[Bar]) || 0'
0
1

显然,您发现了缓存失效没有发生的情况。我认为这是一个错误。 splice 可能由于某种原因没有适当地调用 isa 魔法。您可以尝试以另一种方式修改@ISA,例如使用unshift 或赋值,或者可能尝试mro::method_changed_in,这会使绑定到各种@ISAs 的方法解析缓存无效。

如果您可以将此错误减少到最小的测试用例,那将对修复此错误非常有帮助。

更新:

一个最小的测试用例变得很简单:

$ perl -E'say Foo->isa(q[Bar]) || 0; splice @Foo::ISA, 0, 0, q[Bar]; say Foo->isa(q[Bar]) || 0'
0
0

这是由pp_splice 没有执行mg_set((SV *)ary) 之类的操作引起的。 pushunshift 和常规分配正确地做到了这一点,因此使用其中之一应该可以解决您的问题。

另一个更新:

This change,我刚刚提交给 perl,解决了这个问题。然而,由于splice 不调用魔法的奇怪行为已经出现在 5.8 和 5.10 中,它不是回归,因此在几个月内不会成为 5.12.3 的一部分。下周发布的5.13.6,明年北方春天的5.14.0,大概会有吧。

【讨论】:

以上是关于在@ISA 上使用拼接在 perl 5.12.2 中是不是存在问题?的主要内容,如果未能解决你的问题,请参考以下文章

你如何在 Perl 中创建对象?

Perl在Linux系统下,快速拼接多个文件

如何在使用 perlbrew 时安装 CPAN 模块?

Perl:在 Moose 类中添加编写器拒绝属性访问

Perl Moose 属性句柄设置方法

Perl:如何从@EXPORT 打印变量和值