Как вставить новые поля в $ self в Perl из обратного вызова File :: Find - PullRequest
1 голос
/ 31 марта 2011

В объекте Perl я пытаюсь добавить новое поле в $self из подпрограммы File :: Find wanted().

use File::Find;

sub _searchForXMLDocument {
    my ($self) = @_; 
    if($_ =~ /[.]+\.xml/) {
        $self->{_xmlDocumentPath} = $_;
    }
}


sub runIt{
    my ($self) = @_;
    find (\&_searchForXMLDocument, $self->{_path});
    print $self->{_xmlDocumentPath};
}

_searchForXMLDocument() ищет XML-документ в $self->{_path} и должен добавить этот путь XML к $self->{_xmlDocumentPath}, но когда я пытаюсь его распечатать, он остается неинициализированным. Как добавить поле в $self?

Use of uninitialized value in print at /home/scott/workspace/CCGet/XMLProcessor.pm line 51.

Ответы [ 3 ]

3 голосов
/ 31 марта 2011

Первый аргумент find() должен содержать две части информации: условие теста и объект, с которым вы работаете. Способ сделать это с закрытием. sub { ... } создает код ref, как вы получаете из \&_searchForXMLDocument, но у замыкания есть доступ к лексическим переменным во входящей области, поэтому текущий объект ($self) связан с замыканием.

sub _searchForXMLDocument {
    my ($self) = @_;
    if($_ =~ /[.]+\.xml/) {
        $self->{_xmlDocumentPath} = $_;
    }
}


sub runIt{
    my ($self) = @_;
    find (sub { $self->_searchForXMLDocument (@_) }, $self->{_path});
    print $self->{_xmlDocumentPath};
}
3 голосов
/ 31 марта 2011

Вы не вызываете _searchForXMLDocument () в режиме OO, поэтому ваш объект $ self не передается ему.Это должно сделать свое дело сейчас.Используйте закрытие для вашего метода, и у вас есть доступ к $ self;

sub runIt{
    my ($self) = @_;

    my $closure = sub {
        if($_ !~ m/[.]+\.xml/) {
            $self->{_xmlDocumentPath} = $_;
        }
    };

    find(\&$closure, $self->{_path});
    print $self->{_xmlDocumentPath};
}
2 голосов
/ 31 марта 2011

Я думаю, вы ищете что-то вроде этого:

package XMLDocThing;
use strict;
use warnings;
use English    qw<$EVAL_ERROR>;
use File::Find qw<find>;
...

use constant MY_BREAK = do { \my $v = 133; };

sub find_XML_document { 
    my $self = shift;
    eval { 
        find( sub {
                 return unless m/[.]+\.xml/;
                 $self->{_xmlDocumentPath} = $_;
                 die MY_BREAK;
              }
            , $self->{_path} 
            );
    };
    if ( my $error = $EVAL_ERROR ) { 
        die Carp::longmess( $EVAL_ERROR ) unless $error == MY_BREAK;
    }
}

...
# meanwhile, in some other package...

$xmldocthing->find_XML_document;

Вы передаете закрытие, чтобы найти, и он может получить доступ к $self из содержащей области. File::Find::find не имеет возможности сдавать багаж как предметы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...