我正在构建一个依赖Moose的Perl应用程序。 Moose对象需要完成的一项任务是使用File :: Find来填充带有文件列表的属性。我在查明如何使用find的\&wanted
代码引用方面遇到了一些麻烦,这种方式可以让我保持对Moose对象的$self
版本的访问。
到目前为止,我有这个:
#!/usr/bin/perl
package MyMoose;
use Modern::Perl;
use Moose;
use File::Find;
use FindBin qw($Bin);
### Attribute to hold the file list
has "file_list" => (
is => 'rw',
isa => 'ArrayRef',
default => sub {[]}
);
### Method to populate the file list
sub update_file_list {
my $self = shift;
find(\&wanted, $Bin);
}
### File::Find wanted sub
sub wanted {
### This won't work, but shows what I'd like to do
# my $self = shift;
# ### Do some filtering
# push @{$self->file_list}, $File::Find::name;
}
1;
######################################################################
### Main package to test the object.
package main;
use Data::Dumper;
run_main() unless caller();
sub run_main {
my $m = MyMoose->new();
$m->update_file_list();
print Dumper $m->file_list;
}
它运行,但显然没有组装文件列表。这是我想弄清楚的部分。
使用File :: Find的正确方法是什么,以便在处理过程中让您可以访问Moose对象?
答案 0 :(得分:3)
问题是您无法访问$self
子wanted
内的default
。您可以使用内联关闭和builder
或has "file_list" => (
is => 'rw',
isa => 'ArrayRef',
default => sub {
my $self = shift;
return $self->_get_file_list();
},
);
sub update_file_list {
my $self = shift;
$self->file_list($self->_get_file_list());
}
sub _get_file_list {
my @files;
find(sub { push @files, $File::Find::name }, $Bin);
return \@files;
}
来构建列表。
修改每个更新问题的更新代码
_get_file_list
default
方法返回找到的文件的arrayref。它在update_file_list
和{{1}}方法中用于填充属性。
答案 1 :(得分:0)
正如bvr所说,传递给find
的子例程引用不需要是命名包方法 - 词法closure也可以正常工作。因此,您可以这样做:
sub update_file_list {
my $self = shift;
my $wanted = sub {
### Do some filtering
push @{$self->file_list}, $File::Find::name;
};
find($wanted, $Bin);
}
在外部函数作用域中声明的词法变量$self
将在内部函数中可见。
特别是,每次调用update_file_list
方法时,都会创建一个新的$self
和一个新的$wanted
(并通过$self
的内部引用绑定在一起),以便在不同的对象上多次调用该方法是完全安全的,甚至可以在需要时递归调用。
答案 2 :(得分:0)
经过一些试验错误后,我还通过用以下内容替换原始版本的“update_file_list”来使脚本工作:
sub update_file_list {
my $self = shift;
find( sub { wanted($self); }, $Bin );
}
这似乎也有效。