2010-08-30 3 views
6

По всему месту, особенно в DBI, я вижу, что это сообщение появляется постоянно. Это сбивает с толку, потому что первое, что приходит в голову, это то, что аргументы, передаваемые функцией, устанавливаются в undef (или что-то подобное), но это явно не так.

Учитывая модуль и соответствующий скрипт ...

Модуль: ./lib/My/Module.pm

package My::Module; 

use strict; 
use warnings; 

sub trim { 
    my $str = shift; 
    $str =~ s{ \A \s+ }{}xms; # remove space from front of string 
    $str =~ s{ \s+ \z }{}xms; # remove space from end of string 
    return $str; 
} 

Сценарий: ./test.pl

#!/usr/bin/perl 

use strict; 
use warnings; 
use My::Module qw(trim); 

print $My::Module->trim(" \t hello world\t \t"); 

я возвращусь сообщение об ошибке,

Калифорния не вызывается метод «подрезать» на неопределенное значение в ./text.pl строке 7.

Infact, если я позвоню $My::Module->notamethod("hello world"); дает подобную ошибку.

Что случилось с вышеупомянутым скриптом/модулем?

Что это за ошибка Can't call method “X” on an undefined value at ${SOMEFILE} line ${SOMELINE} действительно говорит? Это относится к контексту вызова метода (переданному здесь для печати) или контексту аргументов?

ответ

6

Этот синтаксис ищет объект или имя класса в переменной $My::Module и вызывает его метод trim, но эта переменная не определена.

Вместо этого вы хотите просто сказать print My::Module::trim(" \t hello world\t \t");, чтобы вызвать функцию My :: Module :: trim().

Из строки использования, похоже, вы пытаетесь импортировать trim() в локальный пакет, чтобы вы могли просто назвать его без квалификации My::Module::, но ваш модуль не выглядит так, как будто он настроен для поддержки экспорта ,

В ваших регулярных выражениях флаги/s и/m не имеют никакого эффекта - они изменяют только что.,^И $ match, и вы не используете их.

+0

Я склонен вставлять их при написании регулярных выражений, потому что мне нравится добавлять комментарии в строку :). Я просто забыл взять их ради примера. – heymatthew

+1

@ The Daemons Advocate,/s и/m не имеют никакого отношения к встроенным комментариям. Это/x. – cjm

-1

Это как Perl делает OO. Разница заключается в том, как вы называете методы.

Это просто вызывает обшивку к югу в My :: Module пакет:

My::Module::trim('foo') 

С другой стороны,

My::Module->trim('foo) 

автоматически становится вызовом обрезной подразделам в My :: Пакет модулей со строкой «My :: Module» в качестве первого аргумента. объектов работают точно так же:

my $m = My::Module->new; # Corrected. Thanks for pointing this out. 
$m->trim('foo'); 

превращается в призыв к тому же к югу, но на этот раз с ссылкой на объект $ м в качестве первого аргумента.

То, что вы пытаетесь сделать, это:

$My::Module->trim('foo'); 

Который переводит к разыменованию переменных $ My :: Module (который не существует), таким образом, сообщение об ошибке «Не удается вызвать метод X по неопределенному значению ". Если $ My :: Module был фактической ссылкой на объект, это привело бы к вызову trim() для этого объекта с ссылкой как неявный первый аргумент.

Редактировать: Оба комментатора верны. Этот ответ изначально был предназначен для комментариев к принятому ответу. (Есть ли способ исправить это?)

Извините за путаницу. Я добавил здесь немного больше подробностей, поэтому, надеюсь, становится более понятным, как это связано с исходным вопросом (разыменование неопределенной переменной).

+1

Вы не должны использовать синтаксис косвенного метода для вашей 'новой' линии. См. Здесь, почему: http://stackoverflow.com/questions/429657/what-is-the-difference-between-new-someclass-and-someclass-new-in-perl/429798#429798 – friedo

+0

Информация в этом сообщении это правда, но на самом деле это не имеет никакого отношения к вопросу. – jrockway

13

Вы объединяете несколько способов обработки модулей и объектов - и в конечном итоге с тем, что не работает.

Вот четыре подхода, которые делают работу:

1/My :: Модуль представляет собой библиотеку. отделка не экспортируется.

$ cat My/Module.pm 
package My::Module; 

use strict; 
use warnings; 

sub trim { 
    my $str = shift; 

    $str =~ s{ \A \s+ }{}xms; # remove space from front of string 
    $str =~ s{ \s+ \z }{}xms; # remove space from end of string 
    return $str; 
} 

1; 
$ cat test 
#!/usr/bin/perl 

use strict; 
use warnings; 

use My::Module; 

# Note: No $ and :: not -> 
print My::Module::trim(" \t hello world\t \t"); 

2/Мой: Модуль - это библиотека. отделка экспортируется.

$ cat My/Module.pm 
package My::Module; 

use strict; 
use warnings; 

use Exporter; 
our @ISA = qw(Exporter); 
our @EXPORT = qw(trim); 

sub trim { 
    my $str = shift; 

    $str =~ s{ \A \s+ }{}xms; # remove space from front of string 
    $str =~ s{ \s+ \z }{}xms; # remove space from end of string 
    return $str; 
} 

1; 
$ cat test 
#!/usr/bin/perl 

use strict; 
use warnings; 

use My::Module; 

print trim(" \t hello world\t \t"); 

3/MyModule - это класс. trim - метод класса.

$ cat My/Module.pm 
package My::Module; 

use strict; 
use warnings; 

sub trim { 
    # Note class name passed as first argument 
    my $class = shift; 
    my $str = shift; 

    $str =~ s{ \A \s+ }{}xms; # remove space from front of string 
    $str =~ s{ \s+ \z }{}xms; # remove space from end of string 
    return $str; 
} 

1; 
$ cat test 
#!/usr/bin/perl 

use strict; 
use warnings; 

use My::Module; 

# Note: Not $ and -> not :: 
print My::Module->trim(" \t hello world\t \t"); 

4/MyModule - класс, отделка - метод объекта.

$ cat My/Module.pm 
package My::Module; 

use strict; 
use warnings; 

# Need a constructor (but this one does nothing useful) 
sub new { 
    my $class = shift; 

    return bless {}, $class; 
} 

sub trim { 
    # Note: Object method is passed an object (which is ignored here) 
    my $self = shift; 
    my $str = shift; 

    $str =~ s{ \A \s+ }{}xms; # remove space from front of string 
    $str =~ s{ \s+ \z }{}xms; # remove space from end of string 
    return $str; 
} 

1; 
$ cat test 
#!/usr/bin/perl 

use strict; 
use warnings; 

use My::Module; 

my $trimmer = My::Module->new; 

print $trimmer->trim(" \t hello world\t \t"); 

Я думаю, что вы пытаетесь для варианта 1. В этом случае, я думаю, что я рекомендовал бы вариант 2.

И ответить на ваш последний вопрос. Вы получаете эту ошибку, потому что пытаетесь вызвать метод для переменной ($ My :: Module), которая не определена.

Смежные вопросы