Как я могу использовать Perl's File :: Find внутри Moose Object? - PullRequest
3 голосов
/ 07 февраля 2012

Я создаю приложение на Perl, которое опирается на Moose. Одной из задач, которую должен выполнить объект Moose, является использование File :: Find для заполнения атрибута списком файлов. У меня возникли проблемы с выяснением того, как использовать ссылку на код поиска \&wanted таким образом, чтобы я мог поддерживать доступ к $self версии объекта Moose.

Пока у меня есть это:

#!/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 ]

3 голосов
/ 07 февраля 2012

Проблема в том, что у вас нет доступа к $self в wanted sub.Вы можете использовать встроенное закрытие и 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 методвозвращает arrayref найденных файлов.Он используется в методе default и update_file_list для заполнения атрибута.

0 голосов
/ 08 февраля 2012

После некоторой пробной ошибки я также заставил скрипт работать, заменив оригинальную версию update_file_list следующим:

sub update_file_list {

    my $self = shift;

    find( sub { wanted($self); }, $Bin );

}

Это также работает.

0 голосов
/ 07 февраля 2012

Как отмечает bvr, ссылка на подпрограмму, переданная в find, не обязательно должна быть именованным методом пакета & mdash; лексическое замыкание будет работать просто отлично. Таким образом, вы можете сделать это:

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), так что это совершенно безопасно для вызовите метод несколько раз для разных объектов, даже если вы хотите рекурсивно.

...