Когда следует использовать переменную пакета против лексической переменной (и в чем разница)? - PullRequest
4 голосов
/ 19 июня 2009

Я смотрю на более старый код Perl на Perl Monks , чтобы разобраться в программировании с Win32 :: OLE и MS Word. Повсюду в коде разбросаны переменные с именами, такими как $ MS :: Word и т. П., Без ' my ', включенных в их объявление. Прочитав немного в Google, я понимаю, что они называются «переменными пакета» по сравнению с «лексическими переменными», объявленными с использованием my .

Мой первый вопрос: « Для чего нужны переменные пакета? ». Я (думаю) я понимаю, что такое лексические переменные, но я не понимаю назначения переменных пакета или того, как их использование отличается от лексических, поэтому мой второй вопрос будет таким: « В чем разница между лексическими и пакетными переменными

Ответы [ 3 ]

8 голосов
/ 19 июня 2009

Вы должны прочитать Справиться со Скопингом по MJD.

perldoc perlmod также было бы полезно прочитать.

Код из этого мира безобразен. Он попирает все виды пространств имен без беспокойства в мире только потому, что автор, кажется, думает, что $ author :: email - это круто.

Лучше было бы использовать хеш:

my %author = (
   email => 'author@example.com',
   ...
);

Не нужно топтать всю таблицу символов.

У меня есть несколько Win32::OLE примеров: http://www.unur.com/comp/, которые не являются произведениями искусства, но я считаю, что улучшения в этом стиле. См. Также Почему количество страниц в документе Word различается в Perl и Word VBA?

Я собираюсь разглагольствовать немного :

@pgm::runtime_args = @ARGV ;

Итак, мы отказываемся от стандартного массива @ARGV, который попирает пространство имен pgm. Мало того, каждый программист на Perl знает, что такое @ARGV. В любом случае @pgm::runtime_args больше не используется в скрипте.

$pgm::maxargs = $#pgm::runtime_args + 1 ;

Конечно, @pgm::runtime_args в скалярном контексте даст нам количество элементов в этом массиве. Я понятия не имею, почему $pgm::maxargs может понадобиться, но если бы это было так, то эта строка должна была бы быть:

$pgm::maxargs = @pgm::runtime_args;

Я не собираюсь цитировать больше этого материала. Я думаю, это то, что происходит, когда программисты на Cobol пытаются писать на Perl.

$program::copyright = "Copyright (c) 02002 - Kenneth Tomiak : All rights reserved.";

Я рад, что он выделил пять цифр за год. Я никогда не знаю!

PS: Я считаю, что мои выдержки представляют собой добросовестное использование.

7 голосов
/ 20 июня 2009

Переменная пакета находится в таблице символов, поэтому, учитывая ее имя, можно прочитать или изменить ее из любого другого пакета или области. Область действия лексической переменной определяется текстом программы. Раздел "Частные переменные через my ()" на странице руководства perlsub дает более подробную информацию об определении лексических символов.

Скажем, у нас есть следующее MyModule.pm:

package MyModule;

# these are package variables
our $Name;
$MyModule::calls = "I do not think it means what you think it means.";

# this is a lexical variable
my $calls = 0;

sub say_hello {
  ++$calls;

  print "Hello, $Name!\n";
}

sub num_greetings {
  $calls;
}

1;

Обратите внимание, что он содержит пакет $calls и лексический $calls. Любой может добраться до первого, но модуль контролирует доступ ко второму:

#! /usr/bin/perl

use warnings;
use strict;

use MyModule;

foreach my $name (qw/ Larry Curly Moe Shemp /) {
  $MyModule::Name = $name;
  MyModule::say_hello;
}

print MyModule::num_greetings, "\n";

print "calls = $MyModule::calls\n";

Вывод программы

Hello, Larry!
Hello, Curly!
Hello, Moe!
Hello, Shemp!
4
calls = I do not think it means what you think it means.

Как видите, переменные пакета являются глобальными, поэтому все обычные ошибки и советы не применяются. Если явно не предоставлен доступ, для кода вне пакета MyModule невозможно получить доступ к его лексическому $calls.

Практическое правило: вы почти всегда хотите использовать лексические выражения. Perl Best Practices Дамиана Конвея прямая: « Никогда не делайте переменные частью интерфейса модуля » (выделено в оригинале).

4 голосов
/ 19 июня 2009

Пакетные переменные являются глобальными переменными;они видны везде во всей программе (даже в других модулях).Они полезны, когда вы хотите или нуждаетесь в этом уровне видимости и / или внешнего влияния.Например, модуль Text :: Wrap использует их, чтобы разрешить одну точку конфигурации для количества столбцов, в которые переносится текст.Более того, переменные пакета позволяют вам использовать то, что называется «динамическая область видимости» - но это несколько продвинутая и немного эзотерическая концепция.

По второму вопросу см. В чем разница между my и our inPerl?

...