Как работает этот вызов подпрограммы в модуле Perl? - PullRequest
10 голосов
/ 08 апреля 2011

Недавно я увидел какой-то Perl-код, который смутил меня.Я вынул все дополнительные части, чтобы посмотреть, как это работает, но я до сих пор не понимаю, почему это работает.

По сути, я создал этот фиктивный "модуль" (TTT.pm):

use strict;
use warnings;

package TTT;
sub new {
    my $class = shift;
    return bless {'Test' => 'Test'}, $class;
}

sub acquire {
    my $tt = new TTT();
    return $tt;
}
1;

Затем я создал этот скрипт для использования модуля (ttt.pl):

#!/usr/bin/perl
use strict;
use warnings;

use TTT;
our $VERSION = 1;

my $tt = acquire TTT;
print $tt->{Test};

Строка, которая меня смущает, я думал, что она не будет работать, это:

my $tt = acquire TTT;

Я думал, что это не сработает, поскольку сабвуфер "никогда не экспортировался".Но это работает.Я был сбит с толку "TTT" после звонка на приобретение, поэтому я удалил его, оставив строку так:

my $tt = acquire;

И он жаловался на голое слово, как я и думал.Я добавил парены, как это:

my $tt = acquire();

И он пожаловался, что не было main::acquire, как я думал, что будет.

Я привык к доступным подпрограммамк объекту или экспортируемым подпрограммам, но я никогда не видел, чтобы вызывали подпрограммы с именами пакетов в конце.Я даже не знаю, как искать это в Google.

Итак, мой вопрос: как работает добавление имени пакета после вызова подпрограммы?Я никогда не видел ничего подобного раньше, и, вероятно, это не очень хорошая практика, но кто-то может объяснить, что делает Perl?

Спасибо!

Ответы [ 2 ]

11 голосов
/ 08 апреля 2011

Вы используете косвенный объектный синтаксис, который допускает Perl (но в современном коде не рекомендуется). Как правило, если имя не объявлено заранее, его можно поместить перед объектом (или именем класса), разделенным пробелом.

Таким образом, строка acquire TTT фактически означает TTT->acquire. Если у вас на самом деле была подпрограмма с именем acquire в области видимости, вместо этого она будет интерпретироваться как aquire(TTT), что может привести к двусмысленности (следовательно, почему она не рекомендуется).

Вы должны также обновить строку new TTT(); в методе, чтобы она читалась как TTT->new;

6 голосов
/ 08 апреля 2011

Это синтаксис косвенного объекта для вызовов методов, который позволяет поставить имя метода перед именем объекта.

Как видно из документации, лучше всегоизбегать, потому что это громоздко и может сломаться непредсказуемым образом, например, если есть импортированная или определенная подпрограмма с именем acquire - но раньше она была более распространенной, чем сегодня, и поэтому вы найдетеэто довольно часто в старом коде и документах.

...