Банально, что вы должны использовать local
, потому что my *FH
- синтаксическая ошибка.
«Правильный» (но не очень поучительный) ответ заключается в том, что вы делаете это неправильно. Вместо этого вы должны использовать лексические файловые дескрипторы и форму с тремя аргументами open
.
sub newopen {
my $path = shift;
my $fh;
open($fh, '<', $path) or do {
warn "Can't read file '$path' [$!]\n";
return;
}
return $fh;
}
Чтобы действительно ответить , почему требуется объяснить разницу между лексическими и глобальными переменными, а также между областью действия переменной и ее продолжительностью.
Область действия переменной - это часть программы, в которой ее имя допустимо. Область действия является статическим свойством. Длительность переменной, с другой стороны, является динамическим свойством. Продолжительность - это время, в течение которого программа существует, и переменная существует и содержит значение.
my
объявляет лексическую переменную. Лексические переменные имеют область видимости от точки объявления до конца включающего блока (или файла). Вы можете иметь другие переменные с одинаковыми именами в разных областях без конфликта. (Вы также можете повторно использовать имя в перекрывающихся областях, но не делайте этого.) Длительность лексических переменных управляется подсчетом ссылок. Пока существует хотя бы одна ссылка на переменную, значение существует, даже если имя недопустимо в определенной области видимости! my
также имеет эффект времени выполнения - он выделяет новую переменную с заданным именем.
local
немного отличается. Он работает с глобальными переменными. Глобальные переменные имеют глобальную область действия (имя действует везде) и продолжительность всей жизни программы. local
временно изменяет значение глобальной переменной. Это иногда называют «динамическим определением». Изменение начинается в точке объявления local
и сохраняется до конца включающего блока, после которого восстанавливается старое значение. Важно отметить, что новое значение не ограничивается блоком - оно видно везде (включая вызываемые подпрограммы). Правила подсчета ссылок по-прежнему применяются, поэтому вы можете взять и сохранить ссылку на локализованное значение после истечения срока изменения.
Вернуться к примеру: *FH
- глобальная переменная. Точнее, это «typeglob» - контейнер для набора глобальных переменных. Тип-глоб содержит слот для каждого из основных типов переменных (скаляр, массив, хэш), а также несколько других вещей. Исторически сложилось, что Perl использовал typeglobs для хранения файловых дескрипторов, и local
-изменение их помогло гарантировать, что они не забивают друг друга. У лексических переменных нет typeglobs, поэтому высказывание my *FH
является синтаксической ошибкой.
В современных версиях Perl лексические переменные могут и должны использоваться вместо файловых дескрипторов. И это возвращает нас к «правильному» ответу.