我的代码大致如下:
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
时才会出现此错误。
答案 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$/');