【问题标题】:How can I use Perl's File::Find inside a Moose Object?如何在 Moose 对象中使用 Perl 的 File::Find?
【发布时间】:2012-02-07 16:38:09
【问题描述】:

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

【问题讨论】:

标签: perl moose


【解决方案1】:

问题是您无权访问$self 内的wanted sub。您可以使用内联闭包和defaultbuilder 来构建列表。

编辑:每个更新问题的更新代码

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 方法返回找到的文件的数组引用。在defaultupdate_file_list 方法中都使用它来填充属性。

【讨论】:

  • 在原始示例中,我不应该将调用置于 BUILD 中。我实际上需要能够通过它自己的方法任意更新文件列表。 (我已经更新了问题示例代码来表示这一点。)所以,默认在这里没有帮助。我会看一下 builder 以了解它的行为。
  • @AlanW.Smith - 请查看更新。 Builder 实际上与默认没有什么不同,您只需按名称指定方法,因此您可以从子类中覆盖它中受益。
【解决方案2】:

正如 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 的内部引用绑定在一起),因此它是完全安全的在不同的对象上多次调用该方法,如果需要,甚至可以递归。

【讨论】:

    【解决方案3】:

    在尝试了一些错误之后,我还通过将“update_file_list”的原始版本替换为以下内容来使脚本正常工作:

    sub update_file_list {
    
        my $self = shift;
    
        find( sub { wanted($self); }, $Bin );
    
    }
    

    这似乎也有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-20
      • 1970-01-01
      • 2018-09-05
      • 1970-01-01
      • 1970-01-01
      • 2013-08-31
      • 1970-01-01
      • 2014-04-20
      相关资源
      最近更新 更多