无法通过包找到对象方法,即使我没有使用方法

Can't locate object method via package, even though I'm not using methods

我的代码大致是这样的:

sub define_pattern { push @Internal::patterns, $_[0]; }

package Internal {
    our @patterns = ();

    sub func { define_pattern { pattern => '(.*)\.c$' }; }
}

Internal::func;

(当然,这是一个简化版!)现在,当我运行它时,它输出:

Can't locate object method "define_pattern" via package "pattern" (perhaps you forgot to load "pattern"?) at x.pl line 6.

我已经用谷歌搜索了这个错误并查看了几个类似的 SO 问题,但是 none 似乎有解决这个问题的方法。为什么 Perl 认为 define_pattern 是方法而 pattern 是包?我认为这个错误只发生在使用 -> 比如 pattern->define_method.

因为子 define_pattern 需要用 () 调用,这只是一个语法错误,除了间接对象语法启动并试图 运行 它作为在 {} 块内计算的对象上的方法(如 ThisSuitIsBlackNot 的回答中所述)。

但是,我也会适当地更改名称空间,并且您需要限定对 define_pattern 的调用。由于存在包存在于同一个编译单元中的限制,我们将其保留在

use warnings;
use strict;

package Internal;
our @patterns;
sub func { 
    main::define_pattern ( pattern => qr/(.*)\.c$/ );
}

package main;

Internal::func;

my @array = @Internal::patterns;

print "Copied onto \@array: |@array|\n";

sub define_pattern { 
  my %in = @_;
  push @Internal::patterns, $in{'pattern'}; 
}
#sub define_pattern { push @Internal::patterns, $_[0]; }

。需要 Internal::func 调用来触发 define_pattern 的操作,因此对全局 @Internal::patterns 的任何使用都必须在 该调用之后进行(在此代码中).所以他们交换了。正则表达式是使用 qr 构建的。 sub 被更改(最小)以便实际将模式存储在全局数组中。代码打印指定的模式:

Copied onto @array: |(?-xism:(.*)\.c$)|

至少能够以最少的更改动态存储模式

package Internal;
our @patterns;
sub func {
    my ($arg) = @_;
    main::define_pattern ( pattern => qr/$arg/ );
}

package main;

Internal::func('(.*)\.c$/');

你被indirect object syntax咬了。 Perl 对此进行解释:

define_pattern { pattern => '(.*)\.c$' };

作为方法的名称,后跟 returns 调用者的块。您可以使用 indirect pragma 看到这一点:

no indirect;

sub define_pattern { push @Internal::patterns, $_[0]; }

package Internal {
    our @patterns = ();

    sub func { define_pattern { pattern => '(.*)\.c$' }; }
}

输出:

Indirect call of method "define_pattern" on a block at foo line 10.

为什么解析器认为 define_pattern 是方法而不是常规子例程?因为 Internal 包中没有名为 define_pattern 的子程序;您在 main.

中定义了它

如果从另一个包中调用非导出的子程序,则必须使用完全限定的子程序名称:

main::define_pattern({ pattern => '(.*)\.c$' });

(如果在调用之前声明了 define_pattern,括号是可选的。)