2016-03-02 5 views
0

У меня есть код примерно так: (! Конечно, это упрощенная версия)Не удается найти метод объекта с помощью пакета, даже если я не использую методы

sub define_pattern { push @Internal::patterns, $_[0]; } 

package Internal { 
    our @patterns =(); 

    sub func { define_pattern { pattern => '(.*)\.c$' }; } 
} 

Internal::func; 

Теперь, когда я бегу он, она выводит:

Can't locate object method "define_pattern" via package "pattern" (perhaps you forgot to load "pattern"?) at x.pl line 6. 

Я уже Googled эту ошибку и посмотрел на несколько похож SO вопросов, но ни один из них не кажется, есть решение этой проблемы. Почему Perl думает, что define_pattern - это метод, а pattern - это пакет? Я думал, что эта ошибка произошла только при использовании ->, например pattern->define_method.

+0

Что означает ваш 'define_pattern'? Вы вызываете его с помощью curlies (и не квалифицируете его как btw). – zdim

+0

@zdim Это обычно немного дольше, но по сути делает то, что он показывает, за исключением того, что полная версия выполняет некоторую проверку и изменение входных параметров. – refi64

ответ

0

Предполагая, что define_pattern необходимо вызвать в качестве суб (с ()), это будет только синтаксической ошибкой. Тем не менее, я также правильно переключался между пространствами имен (пакетов) и квалифицировал бы вызов на define_pattern. Поскольку существует ограничение на то, что пакет должен жить в одном модуле компиляции, мы должны оставить его на этом.

use warnings; 
use strict; 

package Internal; 
our @patterns; 
sub func { 
    main::define_pattern (pattern => qr/(.*)\.c$/); 
} 

package main; 

Internal::func; 

my @array = @Internal::patterns; 

print "Copied onto \@array: |@array|\n"; 

# Functions 
sub define_pattern { 
    my %in = @_; 
    push @Internal::patterns, $in{'pattern'}; 
} 
#sub define_pattern { push @Internal::patterns, $_[0]; } 

Примечание. Поскольку Internal::func требуется вызов для запуска действия define_pattern, любое использование глобального @Internal::patterns должно прибыть после, которые вызывают (в этом коде). Поэтому они переключаются. Regex построен с использованием qr. Суб изменен (минимально), чтобы фактически сохранить шаблон в глобальном массиве. Код печатает указанный шаблон:

 

    Copied onto @array: |(?-xism:(.*)\.c$)| 

Чтобы быть в состоянии, по крайней мере хранить шаблоны динамически, с минимальными изменениями

package Internal; 
our @patterns; 
sub func { 
    my ($arg) = @_; 
    main::define_pattern (pattern => qr/$arg/); 
} 

package main; 

Internal::func('(.*)\.c$/'); 
+0

Нет; он находится в том же файле. Есть * длинный * список действительно грязных причин, но просто предположите, что это необходимо ... – refi64

+0

Кроме того, код * компилирует *, но он не * работает *. Ошибка в 'Internal :: func'. – refi64

+0

Спасибо за помощь! Он работает сейчас! – refi64

4

Вы Укус indirect object syntax. Perl интерпретирует это:

define_pattern { pattern => '(.*)\.c$' }; 

как имя метода, за которым следует блок, возвращающий invocant. Вы можете увидеть это с indirect прагмой:

no indirect; 

sub define_pattern { push @Internal::patterns, $_[0]; } 

package Internal { 
    our @patterns =(); 

    sub func { define_pattern { pattern => '(.*)\.c$' }; } 
} 

Выход:

Indirect call of method "define_pattern" on a block at foo line 10. 

Почему парсер считает, что define_pattern это метод, а не регулярные подпрограммы? Потому что нет подпрограммы с именем define_pattern в пакете Internal; вы определили его в main.

Если вы звоните неэкспортированную подпрограмму из другого пакета, вы должны использовать полное имя подпрограммы: (. Скобки не являются обязательными, если define_pattern объявляются перед тем, как назвать это)

main::define_pattern({ pattern => '(.*)\.c$' }); 

+0

Это полный ответ на весь вопрос и приятный :) +1 – zdim