Когда следует использовать переменную пакета против лексической переменной (и в чем разница)?
Вопрос
Я смотрю на более старый код 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?