Как работает синтаксис Perl? - PullRequest
0 голосов
/ 10 ноября 2010

Код образца:

m1.pm

my $a;
my $b;
sub init {
    $a = shift;
    $b = shift;
}

sub printab {
    print "a = -$a-\n";
    print "b = -$b-\n";
}

1;

m2.pm

my $a;
my $b;
sub init {
    $a = shift;
    $b = shift;
}

1;

test.pl

use strict;
use warnings;

use m1;
use m2;

init('hello', 'world');
printab();

Выполнение:

$ perl test.pl
a = --
b = --
$

Случается так, что вызов init('hello', 'world') сопоставляется с m2.pm и инициализирует переменные ($aи $b) там.

Этот вид имеет смысл, но я не понимаю, почему эти значения недоступны в test.pl.

  • Isчто-то в корне неправильно, что я пытаюсь сделать здесь? Как правильно использовать два модуля с одинаковыми именами подпрограмм и переменных?

  • Как именно работает Perl use?Было бы полезно, если бы кто-то мог противопоставить это директиве C #include.

Ответы [ 3 ]

13 голосов
/ 10 ноября 2010

В Perl ключевое слово use в точности соответствует следующему:

use Mymodule;

#is the same as

BEGIN {
   require Mymodule;
   Mymodule->import();
}

Так что, если вы не определяете подпрограмму импорта в своем коде (или наследуете от Exporter), тогда вашмодули ничего не импортируют в test.pl

Как поймал Синан, вы не объявляете пакет в своих модулях, поэтому они по умолчанию устанавливаются на пакет main.В этом случае все ваши подпрограммы находятся в main, но лексические переменные (объявленные с my) ограничиваются только тем файлом, в котором они объявлены.

Так что m1 определяет sub initи sub printab, к которым относятся лексики $a и $b.Но затем, когда test.pl загружает m2, подпрограмма init перезаписывается новым определением, которое больше не закрывается вокруг двух лексических выражений.Поэтому он записывает в переменные пакета $main::a и $main::b вместо лексических выражений, с которыми связан printab.

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

Вы должны запустить каждый из ваших модулей с:

package Some::Package::Name;
use warnings;
use strict;

, а затем завершить каждый модуль с:

1;

Это потому, чтокогда вы use/require модуль, он должен вернуть истинное значение в конце, чтобы Perl знал, что он загружен правильно.

8 голосов
/ 10 ноября 2010

Сначала прочитайте perldoc perlmod .

Вы не объявляете пространство имен ни в одном модуле, поэтому все находится в пространстве имен main. Объявите package m1; в m1.pm и package m2; в m2.pm.

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

Мне также кажется, что вы исследуете края ОО.

Далее:

  • Избегайте использования $a и $b в качестве имен переменных, поскольку их легко спутать с переменными пакета $a и $b, используемыми sort.

  • Не используйте имена модулей в нижнем регистре: они зарезервированы для прагматов.

Минимальная реализация (все в одном файле для удобства тестирования) выглядит следующим образом:

package My::M1;

use strict; use warnings;

sub new { my $class = shift; bless { @_ } => $class }

sub a {
    my $self = shift;
    my ($v) = @_;
    $self->{a} = $v if @_;
    return $self->{a};
}

sub b {
    my $self = shift;
    my ($v) = @_;
    $self->{b} = $v if @_;
    return $self->{b};
}

package My::M2;

use strict; use warnings;
use base 'My::M1';

sub printtab {
    my $self = shift;
    for my $x (qw(a b)) {
        printf "%s = -%s-\n", $x, $self->$x;
    }
}

package main;

my $m = My::M2->new(a => 'hello', 'b' => 'world');
$m->printtab;
2 голосов
/ 10 ноября 2010

printab() определен в файле m1.pm и имеет доступ только к переменным $a и $b, которые находятся в этом файле.Переменные $a и $b в m2.pm относятся к этому файлу, и они отличаются от переменных , чем $a и $b в m1.pm.

init() устанавливает переменные в области действия m2.pm (потому что это последнее место, где была определена функция &init), поэтому она не устанавливает те переменные, которые printab() будет пытаться вывести.

...