Когда следует использовать переменную пакета против лексической переменной (и в чем разница)?

StackOverflow https://stackoverflow.com/questions/1019617

Вопрос

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

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

Это было полезно?

Решение

Переменная пакета находится в таблице символов, поэтому, учитывая ее имя, можно прочитать или изменить ее из любого другого пакета или области. Область действия лексической переменной определяется текстом программы. Раздел " Частные переменные через my () " на man-странице 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 невозможно получить доступ к его лексическим $ call .

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

Другие советы

Вы должны прочитать Справка с помощью Scoping с помощью 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: я считаю, что мои выдержки представляют собой добросовестное использование.

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

Второй вопрос: В чем разница между моим и нашим в Perl?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top