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

时间:2016-03-02 23:25:56

标签: perl methods runtime-error perl5

我的代码大致如下:

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.

我已经用Google搜索了这个错误并查看了几个类似的SO问题,但似乎没有人能够解决这个问题。为什么Perl认为define_pattern是一种方法而pattern是一个包?我认为只有在使用->之类的pattern->define_method时才会出现此错误。

2 个答案:

答案 0 :(得分:4)

你被indirect object syntax咬了。 Perl解释了这一点:

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

作为返回调用者的块后跟的方法的名称。您可以使用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是方法而不是常规子例程?因为define_pattern包中没有名为Internal的子例程;你在main中定义了它。

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

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

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

答案 1 :(得分:0)

假设define_pattern需要作为sub(())调用,这只会是语法错误。但是,我还要在命名空间(包)之间正确切换,并将调用限定为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";

# Functions
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$/');