如何在Moose对象中使用Perl的File :: Find?

时间:2012-02-07 16:38:09

标签: perl moose

我正在构建一个依赖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对象?

3 个答案:

答案 0 :(得分:3)

问题是您无法访问$selfwanted内的default。您可以使用内联关闭和builderhas "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 );

}

这似乎也有效。