Spec-Zone.ru › Perl 5.36

perldata

СОДЕРЖАНИЕ

  • ИМЯ
  • ОПИСАНИЕ
    • Имена переменных
    • Разбор идентификаторов
    • Контекст
    • Скалярные значения
    • Конструкторы скалярных значений
      • Имена переменных, разделяемые скобками
      • Особые значения с плавающей точкой: бесконечность (Inf) и не число (NaN)
      • Строки версий
      • Специальные литералы
      • Неразмеченные слова
      • Вставка массивов
    • Конструкторы списков значений
    • Индексы
    • Эмуляция многомерных массивов
    • Срезы
      • Срезы хешей ключ/значение
      • Срезы массивов индекс/значение
    • Имена типов и файловые дескрипторы
  • СМОТРИТЕ ТАКЖЕ

ИМЯ

perldata - Типы данных Perl

ОПИСАНИЕ

Имена переменных

В Perl есть три встроенных типа данных: скаляры, массивы скаляров и ассоциативные массивы скаляров, известные как «хэши». Скаляр — это единственная строка (любого размера, ограниченная только доступной памятью), число или ссылка на что-либо (что будет обсуждаться в perlref). Обычные массивы — это упорядоченные списки скаляров, индексированные числами, начиная с 0. Хэши — это неупорядоченные коллекции скалярных значений, индексированные соответствующим строковым ключом.

Значения обычно ссылаются по имени или через указанное имя. Первая буква имени указывает, к какому типу данных оно относится. Остальная часть имени указывает конкретное значение, к которому оно относится. Обычно это один идентификатор, то есть строка, начинающаяся с буквы или подчеркивания и содержащая буквы, подчеркивания и цифры. В некоторых случаях это может быть цепочка идентификаторов, разделенных :: (или несколько устаревшего '); все, кроме последнего, интерпретируются как имена пакетов для поиска пространства имен, в котором нужно искать окончательный идентификатор (см. "Пакеты" в perlmod для получения подробностей). Более подробное обсуждение идентификаторов см. в разделе "Разбор идентификаторов". Можно заменить простой идентификатор выражением, которое возвращает ссылку на значение во время выполнения. Более подробное описание этого приведено ниже и в perlref.

Perl также имеет собственные встроенные переменные, имена которых не следуют этим правилам. У них странные имена, чтобы случайно не столкнуться с вашей обычной переменной. Строки, соответствующие скобочным частям регулярного выражения, сохраняются под именами, содержащими только цифры после $ (см. perlop и perlre). Кроме того, несколько специальных переменных, предоставляющих доступ к внутреннему устройству Perl, имеют имена, содержащие знаки препинания. Они документированы в perlvar.

Скалярные значения всегда обозначаются символом '$', даже при ссылке на скаляр, являющийся частью массива или хэша. Символ '$' семантически работает как английское слово «the», указывая, что ожидается одно значение.

$days               # the simple scalar value "days"
$days[28]           # the 29th element of array @days
$days{'Feb'}        # the 'Feb' value from hash %days
$#days              # the last index of array @days

Целые массивы (и срезы массивов и хэшей) обозначаются символом '@', который работает примерно так же, как слова «эти» или «те» в английском языке, указывая, что ожидается несколько значений.

@days               # ($days[0], $days[1],... $days[n])
@days[3,4,5]        # same as ($days[3],$days[4],$days[5])
@days{'a','c'}      # same as ($days{'a'},$days{'c'})

Целые хэши обозначаются символом '%':

%days               # (key1, val1, key2, val2 ...)

Кроме того, подпрограммы имеют имя, начинающееся с '&', хотя это необязательно, если имя однозначно, так же как слово «do» часто избыточно в английском языке. Элементы таблицы символов могут иметь имя, начинающееся с '*', но вам это пока не нужно (если вообще когда-нибудь нужно).

Каждый тип переменных имеет своё пространство имён, как и несколько идентификаторов, которые не являются переменными. Это означает, что вы можете без опасения использовать одно и то же имя для скалярной переменной, массива или хэша — или, в общем, для файлового дескриптора, дескриптора каталога, имени подпрограммы, имени формата или метки. Это означает, что $foo и @foo — это две разные переменные. Это также означает, что $foo[1] является частью @foo, а не частью $foo. Это может показаться немного странным, но это нормально, потому что это странно.

Поскольку ссылки на переменные всегда начинаются с '$', '@' или '%', «зарезервированные» слова фактически не зарезервированы по отношению к именам переменных. Однако они зарезервированы по отношению к меткам и файловым дескрипторам, которые не имеют начального специального символа. У вас не может быть файлового дескриптора с именем «log», например. Подсказка: вы можете сказать open(LOG,'logfile') вместо open(log,'logfile'). Использование файловых дескрипторов с заглавными буквами также улучшает читаемость и защищает вас от конфликтов с будущими зарезервированными словами. Регистр имеет значение — «FOO», «Foo» и «foo» — это разные имена. Имена, начинающиеся с буквы или подчеркивания, могут также содержать цифры и подчеркивания.

Можно заменить такое буквенно-цифровое имя выражением, возвращающим ссылку на соответствующий тип. Описание этого см. в perlref.

Имена, начинающиеся с цифры, могут содержать только другие цифры. Имена, не начинающиеся с буквы, подчеркивания, цифры или знака «^», ограничены одним символом, например, $% или $$. (Большинство этих имён из одного символа имеют предварительно определённое значение для Perl. Например, $$ — это текущий идентификатор процесса. И все такие имена зарезервированы для возможного использования Perl.)

Разбор идентификаторов

До Perl 5.18 правила для определения допустимого идентификатора были немного размытыми. Однако, как правило, всё определённое здесь должно работать и в предыдущих версиях Perl, в то время как обратное — случаи, которые работают в предыдущих версиях, но не определены здесь — вероятно, не будут работать в новых версиях. Важно отметить, что следующее относится только к идентификаторам «bareword» в исходном коде Perl, а не к идентификаторам, введённым через символьные ссылки, которые имеют гораздо меньше ограничений. Если используется псевдоним use utf8;, применяются следующие правила:

/ (?[ ( \p{Word} & \p{XID_Start} ) + [_] ])
  (?[ ( \p{Word} & \p{XID_Continue} ) ]) *    /x

То есть, символ «начала» следует за любым количеством символов «продолжения». Perl требует, чтобы каждый символ в идентификаторе также соответствовал \w (это предотвращает некоторые проблемные случаи); и Perl дополнительно поддерживает имена идентификаторов, начинающиеся с символа подчеркивания.

Если псевдоним use utf8 не используется, исходный код обрабатывается как ASCII + 128 дополнительных универсальных символов, и идентификаторы должны соответствовать

/ (?aa) (?!\d) \w+ /x

То есть, любой символ слова в диапазоне ASCII, при условии, что первый символ не является цифрой.

В Perl есть два разделителя пакетов: двойное двоеточие (::) и одинарная кавычка ('). Обычные идентификаторы могут начинаться или заканчиваться двойным двоеточием и могут содержать несколько частей, разделяемых двойными двоеточиями. Одинарные кавычки имеют похожие правила, но с исключением, что они не могут быть в конце идентификатора: то есть, $'foo и $foo'bar допустимы, но $foo'bar' — нет.

Кроме того, если идентификатор предваряется символом — то есть, если идентификатор является частью имени переменной — он может дополнительно быть заключён в фигурные скобки.

Хотя вы можете смешивать двойные двоеточия с одинарными кавычками, кавычки должны следовать за двоеточиями: $::::'foo и $foo::'bar допустимы, но $::'::foo и $foo'::bar — нет.

В итоге, грамматика для соответствия базовому идентификатору принимает вид

/
 (?(DEFINE)
     (?<variable>
         (?&sigil)
         (?:
                 (?&normal_identifier)
             |   \{ \s* (?&normal_identifier) \s* \}
         )
     )
     (?<normal_identifier>
         (?: :: )* '?
          (?&basic_identifier)
          (?: (?= (?: :: )+ '? | (?: :: )* ' ) (?&normal_identifier) )?
         (?: :: )*
     )
     (?<basic_identifier>
       # is use utf8 on?
         (?(?{ (caller(0))[8] & $utf8::hint_bits })
             (?&Perl_XIDS) (?&Perl_XIDC)*
           | (?aa) (?!\d) \w+
         )
     )
     (?<sigil> [&*\$\@\%])
     (?<Perl_XIDS> (?[ ( \p{Word} & \p{XID_Start} ) + [_] ]) )
     (?<Perl_XIDC> (?[ \p{Word} & \p{XID_Continue} ]) )
 )
/x

Между тем, специальные идентификаторы не следуют вышеприведённым правилам; в основном, все идентификаторы в этой категории имеют специальное значение, заданное Perl. Поскольку у них есть специальные правила разбора, их обычно нельзя полностью квалифицировать. Они существуют в шести формах (но не используйте формы 5 и 6):

  1. Символ, за которым следуют только цифры, соответствующие \p{POSIX_Digit}, например $0, $1, или $10000.

  2. Символ, за которым следует одиночный символ, соответствующий свойству \p{POSIX_Punct}, например $! или %+, за исключением символа "{", который не работает.

  3. Символ, за которым следует знак «^» и любой из символов [][A-Z^_?\], например $^V или $^].

  4. Аналогично вышесказанному, символ, за которым следует текстовое значение «bareword» в фигурных скобках, где первый символ — это знак «^». Следующий символ — любой из символов [][A-Z^_?\], за которым следуют символы ASCII «word». Пример — ${^GLOBAL_PHASE}.

  5. Символ, за которым следует любой одиночный символ в диапазоне [\xA1-\xAC\xAE-\xFF] при отсутствии "use utf8". (При использовании "use utf8", применяются описанные ранее правила для обычных идентификаторов.) Использование неграфических символов (C1-управляющие символы, NO-BREAK SPACE и SOFT HYPHEN) запрещено с версии v5.26.0. Использование других символов не рекомендуется, так как они все зарезервированы для специальных значений в Perl, и в настоящее время ни один из них не имеет специального значения, хотя это может измениться без предварительного уведомления.

    Обратите внимание, что это означает, что существуют идентификаторы, допустимые только с "use utf8", и наоборот, например, идентификатор $état допустим с "use utf8", но в противном случае считается одиночной переменной $é с последующим «bareword» "tat", сочетание которых является синтаксической ошибкой.

  6. Это комбинация двух предыдущих форм. Допустимо только при отсутствии "use utf8" (при использовании "use utf8" применяются обычные правила идентификаторов). Форма — это символ, за которым следует текст в фигурных скобках, где первый символ — любой из символов в диапазоне [\x80-\xFF] , за которым следуют символы ASCII «word» до закрывающей фигурной скобки.

    Те же оговорки, что и в предыдущей форме: неграфические символы больше не поддерживаются с «use utf8», не рекомендуется использовать эту форму, и utf8-ность имеет большое значение.

До версии Perl v5.24 неграфические ASCII-управляющие символы также допускались в некоторых ситуациях; это было устаревшим с версии v5.20.

Контекст

Интерпретация операций и значений в Perl иногда зависит от требований контекста вокруг операции или значения. Существуют два основных контекста: список и скаляр. Некоторые операции возвращают значения списка в контексте, требующем списка, и скалярные значения в противном случае. Если это верно для операции, это будет упомянуто в документации для этой операции. Другими словами, Perl перегружает определённые операции в зависимости от того, является ли ожидаемое возвращаемое значение единственным или множественным. Некоторые слова на английском языке работают таким образом, например, «рыба» и «овца».

Взаимным образом операция предоставляет каждый своему аргументу либо скалярный, либо списочный контекст. Например, если вы говорите

int( <STDIN> )

операция целочисленного деления предоставляет скалярный контекст для оператора <>, который отвечает считыванием одной строки из STDIN и передачей её обратно операции целочисленного деления, которая затем найдёт целочисленное значение этой строки и вернёт его. Если же, с другой стороны, вы говорите

sort( <STDIN> )

то операция сортировки предоставляет списочный контекст для <>, который будет продолжать читать все доступные строки до конца файла, и передать этот список строк обратно процедуре сортировки, которая затем отсортирует эти строки и вернёт их в виде списка тому, для кого был предназначен контекст сортировки.

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

Когда вы используете use warnings пragma или командную строку Perl -w, вы можете увидеть предупреждения о бесполезном использовании констант или функций в «пустом контексте». Пустой контекст просто означает, что значение было отброшено, например, в утверждении, содержащем только "fred"; или getpwuid(0);. Тем не менее, это всё равно считается скалярным контекстом для функций, которым важно, вызываются ли они в списочном контексте.

Пользовательские подпрограммы могут выбрать, обращать ли они внимание на то, вызываются ли они в пустом, скалярном или списочном контексте. Тем не менее, большинству подпрограмм это не нужно. Это потому, что как скаляры, так и списки автоматически интерполируются в списки. См. "wantarray" в perlfunc, чтобы узнать, как динамически определить контекст вызова вашей функции.

Скалярные значения

Все данные в Perl являются скалярными, массивом скаляров или хэш-таблицей скаляров. Скаляр может содержать одно единственное значение в трёх различных форматах: число, строка или ссылка. В общем случае преобразование из одной формы в другую прозрачно. Хотя скаляр напрямую не может содержать несколько значений, он может содержать ссылку на массив или хэш, который в свою очередь содержит несколько значений.

Скаляры не обязательно являются чем-то одним или другим. Нет места для объявления скалярной переменной как типа «строка», типа «число», типа «ссылка» или чего-либо ещё. Благодаря автоматическому преобразованию скаляров, операции, возвращающие скаляры, не нуждаются в знании (и, на самом деле, не могут знать) хочет ли их вызывающий сторона строку, число или ссылку. Perl — это контекстно-полиморфный язык, чьи скаляры могут быть строками, числами или ссылками (включая объекты). Хотя строки и числа считаются практически одинаковыми для почти всех целей, ссылки являются сильно типизированными, не преобразуемыми указателями с встроенным подсчётом ссылок и вызовом деструктора.

Скалярное значение интерпретируется как ЛОЖЬ в булевом смысле, если оно не определено, является пустой строкой или числом 0 (или его строковым эквивалентом, «0»), и ИСТИНА, если это что-либо ещё. Булевый контекст — это просто специальный вид скалярного контекста, где никогда не выполняется преобразование в строку или число. Отрицание истинного значения с помощью ! или not возвращает специальное ложное значение. При интерпретации как строки оно обрабатывается как "", но как число, оно обрабатывается как 0. Большинство операторов Perl, возвращающих истину или ложь, ведут себя таким образом.

На самом деле существует два типа пустых строк (иногда называемых «пустыми» строками), определённая и неопределённая. Определённая версия — это просто строка длиной ноль, например "". Неопределённая версия — это значение, которое указывает, что для чего-то нет реального значения, например, при ошибке, в конце файла или при ссылке на неинициализированную переменную или элемент массива или хэша. Хотя в ранних версиях Perl неопределённый скаляр мог стать определённым при первом использовании в месте, ожидающем определённое значение, это больше не происходит, кроме редких случаев автовивификации, как объясняется в perlref. Вы можете использовать оператор defined() для определения, является ли скалярное значение определённым (это не имеет смысла для массивов или хэшей), и оператор undef() для создания неопределённого значения.

Чтобы определить, является ли данная строка допустимым ненулевым числом, иногда достаточно проверить её на соответствие как числовому 0, так и лексическому «0» (хотя это вызовет шум, если включены предупреждения). Это потому, что строки, которые не являются числами, считаются равными 0, как и в awk:

if ($str == 0 && $str ne "0")  {
    warn "That doesn't look like a number";
}

Этот метод может быть лучшим, потому что в противном случае вы не будете правильно обрабатывать обозначения IEEE, такие как NaN или Infinity. В других случаях вы можете предпочесть определить, можно ли использовать строковые данные численно, вызвав функцию POSIX::strtod() или проверив свою строку с помощью регулярного выражения (как документировано в perlre).

warn "has nondigits"        if     /\D/;
warn "not a natural number" unless /^\d+$/;             # rejects -3
warn "not an integer"       unless /^-?\d+$/;           # rejects +3
warn "not an integer"       unless /^[+-]?\d+$/;
warn "not a decimal number" unless /^-?\d+\.?\d*$/;     # rejects .2
warn "not a decimal number" unless /^-?(?:\d+(?:\.\d*)?|\.\d+)$/;
warn "not a C float"
    unless /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/;

Длина массива — это скалярное значение. Вы можете найти длину массива @days, вычислив $#days, как и в csh. Однако это не длина массива; это индекс последнего элемента, который отличается, поскольку обычно есть нулевой элемент. Присваивание $#days фактически изменяет длину массива. Укорачивание массива таким образом уничтожает промежуточные значения. Увеличение длины массива, который был предварительно укорочен, не восстанавливает значения, которые были в этих элементах.

Вы также можете получить некоторое небольшое повышение эффективности, предварительно увеличив массив, который будет большим. Вы также можете увеличить массив, присвоив значение элементу, который находится за пределами массива. Вы можете обнулить массив, присвоив ему пустой список (). Следующие выражения эквивалентны:

@whatever = ();
$#whatever = -1;

Если вы вычисляете массив в скалярном контексте, он возвращает длину массива. (Обратите внимание, что это не относится к спискам, которые возвращают последнее значение, как оператор запятой в C, и к встроенным функциям, которые возвращают то, что они посчитают нужным вернуть.) Следующее всегда верно:

scalar(@whatever) == $#whatever + 1;

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

$element_count = scalar(@whatever);

Если вы вычисляете хэш-таблицу в скалярном контексте, она возвращает ложное значение, если хэш пуст. Если имеются пары ключ/значение, она возвращает истинное значение. Более точное определение зависит от версии.

Перед Perl 5.25 возвращаемое значение было строкой, состоящей из количества используемых ведер и количества выделенных ведер, разделённых слэшем. Это практически полезно только для определения того, плохо ли работает внутренний алгоритм хэширования Perl для вашего набора данных. Например, вы помещаете 10 000 элементов в хэш, но вычисление %HASH в скалярном контексте показывает "1/16", что только одно из шестнадцати ведер было затронуто и, предположительно, содержит все ваши 10 000 элементов. Этого не должно происходить.

Начиная с Perl 5.25 возвращаемое значение — это количество ключей в хэше. Если вам нужен доступ к старому поведению, вы можете использовать Hash::Util::bucket_ratio() вместо этого.

Если связанный хэш оценивается в скалярном контексте, вызывается метод SCALAR (с обращением к FIRSTKEY).

Вы можете предварительно выделить память для хэша, присвоив значение функции keys(). Это округляет выделенные ведра до ближайшей степени двойки:

keys(%users) = 1000;                # allocate 1024 buckets

Конструкторы скалярных значений

Числовые литералы задаются в любом из следующих форматов с плавающей запятой или целых чисел:

12345
12345.67
.23E-10             # a very small number
3.14_15_92          # a very important number
4_294_967_296       # underscore for legibility
0xff                # hex
0xdead_beef         # more hex
0377                # octal (only numbers, begins with 0)
0o12_345            # alternative octal (introduced in Perl 5.33.5)
0b011011            # binary
0x1.999ap-4         # hexadecimal floating point (the 'p' is required)

Разрешается использовать нижние подчёркивания в числовых литералах между цифрами для повышения читабельности (но не несколько нижних подчёркиваний подряд: 23__500 недопустимо; 23_500 допустимо). Например, можно группировать двоичные цифры по три (как для аргумента Unix-стиля режима, например, 0b110_100_100) или по четыре (для представления нибблов, как в 0b1010_0110) или в других группах.

Строковые литералы обычно разделяются одинарными или двойными кавычками. Они работают примерно так же, как кавычки в стандартных оболочках Unix: строковые литералы в двойных кавычках подвергаются замене обратной косой чертой и переменными; строковые литералы в одинарных кавычках — нет (кроме \' и \\). Обычно применяются правила обратной косой черты в стиле C для создания символов, таких как перевод строки, табуляция и т. д., а также некоторых более экзотических форм. См. "Quote and Quote-like Operators" в perlop для списка.

Шестнадцатеричные, восьмеричные или двоичные представления в строковых литералах (например, '0xff') не преобразуются автоматически в их целочисленное представление. Функции hex() и oct() выполняют эти преобразования за вас. См. "hex" в perlfunc и "oct" в perlfunc для получения дополнительной информации.

Шестнадцатеричные числа с плавающей запятой могут начинаться так же, как шестнадцатеричный литерал, и могут быть дополнены необязательной дробной шестнадцатеричной частью, но должны быть завершены p, необязательным знаком и степенью двойки. Этот формат полезен для точного представления чисел с плавающей запятой, избегая преобразований в десятичные числа с плавающей запятой и, следовательно, избегая возможной потери точности. Обратите внимание, что, хотя большинство современных платформ используют 64-битное число с плавающей запятой IEEE 754, не все это делают. Ещё одним потенциальным источником (незначительных) различий являются режимы округления чисел с плавающей запятой, которые могут отличаться между процессорами, операционными системами и компиляторами, и Perl не контролирует их.

Вы также можете вставлять переводы строк непосредственно в свои строки, то есть они могут заканчиваться на другой строке, чем начинаются. Это удобно, но если вы забудете заключительную кавычку, ошибка не будет сообщена до тех пор, пока Perl не найдёт другую строку, содержащую символ кавычки, что может произойти значительно позже в скрипте. Подстановка переменных внутри строк ограничена скалярными переменными, массивами и срезами массивов или хэшей. (Другими словами, имена, начинающиеся с $ или @, за которыми следует необязательное выражение в квадратных скобках в качестве индекса.) Следующий фрагмент кода выводит "Цена — $100."

$Price = '$100';    # not interpolated
print "The price is $Price.\n";     # interpolated

В Perl нет двойной интерполяции, поэтому $100 остаётся как есть.

По умолчанию, числа с плавающей запятой, подставляемые в строки, используют точку (".") в качестве десятичного разделителя. Если use locale активен, и вы вызвали POSIX::setlocale(), используемый символ для десятичного разделителя зависит от локали LC_NUMERIC. См. perllocale и POSIX.

Разграниченные имена переменных с использованием фигурных скобок

Как и в некоторых оболочках, вы можете заключить имя переменной в фигурные скобки в качестве разделителя, чтобы избежать неоднозначности с последующими буквенно-цифровыми символами и символами подчёркивания или другим текстом. Это также необходимо при интерполяции переменной в строку, чтобы отделить имя переменной от последующего двойного двоеточия или апострофа, поскольку в противном случае они рассматривались бы как разделители пакетов:

$who = "Larry";
print PASSWD "${who}::0:0:Superuser:/:/bin/perl\n";
print "We use ${who}speak when ${who}'s here.\n";
END_OF_DOCUMENT_MARKER

Без фигурных скобок Perl искал бы переменную $whospeak, $who::0, и $who's. Две последние переменные были бы $0 и $s в (предположительно) несуществующем пакете who.

На самом деле, простой идентификатор внутри таких фигурных скобок принудительно преобразуется в строку, так же как и внутри индекса хэша. Ничего цитировать не нужно. Наш предыдущий пример, $days{'Feb'}, может быть записан как $days{Feb}, и кавычки будут автоматически добавлены. Но всё более сложное в индексе будет интерпретировано как выражение. Это означает, что, например, $version{2.0}++ эквивалентно $version{2}++, а не $version{'2.0'}++.

Существует аналогичная проблема с интерполяцией текста, который выглядит как обозначение доступа к массиву или хэшу. Размещение простой переменной, такой как $who, непосредственно перед текстом, например, "[1]" или "{foo}", приведет к интерполяции переменной как доступа к элементу @who или значению, хранящемуся в %who:

$who = "Larry Wall";
print "$who[1] is the father of Perl.\n";

попытается получить доступ к индексу 1 массива с именем @who. Опять же, использование фигурных скобок предотвратит это:

$who = "Larry Wall";
print "${who}[1] is the father of Perl.\n";

будет обработано так же, как

$who = "Larry Wall";
print $who . "[1] is the father of Perl.\n";

Это обозначение также применяется к более сложным описаниям переменных, таким как доступ к массиву или хэшу с индексами. Например,

@name = qw(Larry Curly Moe);
print "Also ${name[0]}[1] was a member\n";

Без фигурных скобок вышеприведенный пример был бы проанализирован как индекс массива двух уровней в массиве @name, и под use strict, вероятно, произошла бы фатальная ошибка, так как он был бы проанализирован так:

print "Also " . $name[0][1] . " was a member\n";

а не так, как предполагалось:

print "Also " . $name[0] . "[1] was a member\n";

Аналогичный результат может быть получен с помощью обратного слэша в начале индекса или обозначения пакета, которые не являются частью переменной, к которой вы хотите получить доступ. Таким образом, вышеприведенный пример также может быть записан:

@name = qw(Larry Curly Moe);
print "Also $name[0]\[1] was a member\n";

Однако для некоторых специальных переменных (переменные с несколькими символами перед каретом) обозначенная форма с использованием фигурных скобок является единственным способом ссылки на переменную и единственным способом доступа к индексу переменной посредством интерполяции.

Рассмотрим магический массив @{^CAPTURE}, который заполняется движком регулярных выражений содержимым всех буферов захвата в шаблоне (см. perlvar и perlre). Единственный способ доступа к одному из этих элементов внутри строки — это обозначенная форма с фигурными скобками:

"abc"=~/(.)(.)(.)/
    and print "Second buffer is ${^CAPTURE[1]}";

эквивалентно

"abc"=~/(.)(.)(.)/
    and print "Second buffer is " . ${^CAPTURE}[1];

Написание @^CAPTURE — синтаксическая ошибка, поэтому она должна быть указана как @{^CAPTURE}, а для доступа к одному из её элементов в обычном коде вы бы написали ${^CAPTURE}[1] . Однако при интерполяции в строке "${^CAPTURE}[1]" эквивалентно ${^CAPTURE} . "[1]", что даже не относится к той же переменной! Таким образом, индексы также должны быть помещены внутри фигурных скобок: "${^CAPTURE[1]}".

Обозначенная форма с использованием фигурных скобок может быть использована со всеми типами доступа к переменным, включая слайсы массивов и хэшей. Например, следующий код:

@name = qw(Larry Curly Moe);
local $" = " and ";
print "My favorites were @{name[1,2]}.\n";

выведет

My favorites were Curly and Moe.

Специальные числа с плавающей точкой: бесконечность (Inf) и не число (NaN)

Числа с плавающей точкой включают специальные значения Inf и NaN, для бесконечности и не числа. Бесконечность также может быть отрицательной.

Бесконечность является результатом определённых математических операций, которые переполняют диапазон чисел с плавающей точкой, например, 9**9**9. Не число — результат, когда результат не определён или не может быть представлен. Обратите внимание, что вы не можете получить NaN от некоторых общих операций «не определено» или «вне диапазона», таких как деление на ноль или квадратный корень из отрицательного числа, так как Perl генерирует фатальные ошибки для них.

Бесконечность и не число имеют свои специальные правила арифметики. Общее правило состоит в том, что они «заразны»: Inf плюс один равно Inf, и NaN плюс один равно NaN. Интересно, когда вы комбинируете бесконечности и не числа: Inf минус Inf и Inf делённое на Inf равно NaN (в то время как Inf плюс Inf равно Inf и Inf умноженное на Inf равно Inf). NaN также любопытно, так как оно не равно ни одному числу, включая и себя: NaN != NaN.

Perl не понимает Inf и NaN как числовые литералы, но вы можете иметь их как строки, и Perl преобразует их по мере необходимости: "Inf" + 1. (Однако вы можете импортировать их из расширения POSIX; use POSIX qw(Inf NaN);, а затем использовать их как литералы.)

Обратите внимание, что при вводе (строка в число) Perl принимает Inf и NaN во многих форматах. Регистр игнорируется, и понимаются специфичные для Win32 формы, такие как 1.#INF, но при выводе значения нормализуются до Inf и NaN.

Строки версий

Литерал вида v1.20.300.4000 интерпретируется как строка, составленная из символов со специфицированными порядковыми номерами. Этот формат, известный как v-строки, предоставляет альтернативный, более читабельный способ построения строк вместо несколько менее читабельной формы интерполяции "\x{1}\x{14}\x{12c}\x{fa0}". Это полезно для представления строк Юникод и для сравнения версий «чисел» с использованием операторов сравнения строк, cmp, gt, lt и т. д. Если в литерале есть две или более точки, ведущий v может быть опущен.

print v9786;              # prints SMILEY, "\x{263a}"
print v102.111.111;       # prints "foo"
print 102.111.111;        # same

Такие литералы принимаются как require, так и use для проверки версии. Обратите внимание, что использование v-строк для адресов IPv4 не является переносимым, если вы также не используете функции inet_aton()/inet_ntoa() пакета Socket.

Обратите внимание, что с Perl 5.8.1 одночисловые v-строки (например, v65) не являются v-строками до оператора => (который обычно используется для разделения ключа хэша и значения хэша); вместо этого они интерпретируются как литеральные строки ('v65'). Они были v-строками с Perl 5.6.0 по Perl 5.8.0, но это вызывало больше путаницы и сбоев, чем пользы. Многочисловые v-строки, такие как v65.66 и 65.66.67, по-прежнему всегда являются v-строками.

Специальные литералы

Специальные литералы __FILE__, __LINE__ и __PACKAGE__ представляют текущее имя файла, номер строки и имя пакета в данной точке вашей программы. __SUB__ возвращает ссылку на текущую подпрограмму. Они могут использоваться только как отдельные токены; они не будут интерполированы в строки. Если нет текущего пакета (из-за пустой package; директивы), __PACKAGE__ имеет неопределённое значение. (Однако пустая package; больше не поддерживается с версии 5.10.) Вне подпрограммы __SUB__ имеет неопределённое значение. __SUB__ доступен только в 5.16 или выше и только с объявлением use v5.16 или use feature "current_sub".

Два управляющих символа ^D и ^Z, и токены __END__ и __DATA__ могут быть использованы для указания логического конца скрипта до фактического конца файла. Любой последующий текст игнорируется интерпретатором, если его не прочитает программа, как описано ниже.

Текст после __DATA__ может быть прочитан с помощью файлового дескриптора PACKNAME::DATA, где PACKNAME — пакет, который был текущим, когда был встречен токен __DATA__. Файловый дескриптор остается открытым и указывает на строку после __DATA__. Программа должна close DATA после завершения чтения из него. (Оставление его открытым приводит к утечке файловых дескрипторов, если модуль перезагружается по какой-либо причине, поэтому более безопасной практикой является его закрытие.) Для совместимости со старыми скриптами, написанными до введения __DATA__, __END__ ведёт себя как __DATA__ в скрипте верхнего уровня (но не в файлах, загруженных с require или do и оставляет оставшееся содержимое файла доступным через main::DATA.

while (my $line = <DATA>) { print $line; }
close DATA;
__DATA__
Hello world.

Файловый дескриптор DATA по умолчанию имеет то же самое значение PerlIO, которое было введено, когда Perl прочитал файл для анализа исходного кода. Обычно это означает, что файл читается побайтово, как если бы он был закодирован в Latin-1, но есть два основных способа, как это может быть иначе. Во-первых, если токен __END__/__DATA__ находится в области действия прагмы use utf8, то файловый дескриптор DATA будет в режиме UTF-8. И во-вторых, если исходный код читается из стандартного ввода perl, то файловый дескриптор DATA фактически является псевдонимом файлового дескриптора STDIN, и может быть в режиме UTF-8 из-за переменной среды PERL_UNICODE или параметров командной строки perl.

См. SelfLoader для получения дополнительной информации об __DATA__ и примере его использования. Обратите внимание, что из файлового дескриптора DATA нельзя читать в блоке BEGIN: блок BEGIN выполняется как только он виден (во время компиляции), в этот момент соответствующий токен __DATA__ (или __END__) ещё не виден.

Необработанные слова

Слово, которое не имеет другого толкования в грамматике, будет рассматриваться как строка в кавычках. Эти слова известны как «необработанные слова». Как и с файловыми дескрипторами и метками, необработанное слово, состоящее только из строчных букв, рискует конфликтовать с будущими ключевыми словами, и если вы используете прагму use warnings или флаг -w, Perl предупредит вас об этих словах. Perl ограничивает необработанные слова (как и идентификаторы) примерно 250 символами. Будущие версии Perl, вероятно, уберут эти произвольные ограничения.

Некоторые люди могут пожелать полностью запретить необработанные слова. Если вы говорите

use strict 'subs';

то любое необработанное слово, которое НЕ будет интерпретировано как вызов подпрограммы, вместо этого порождает ошибку во время компиляции. Ограничение действует до конца окружающего блока. Внутренний блок может отменить это, написав no strict 'subs'.

Интерполяция массивов

Массивы и срезы интерполируются в строки с двойными кавычками путём объединения элементов с разделителем, указанным в переменной $" ($LIST_SEPARATOR, если указано "use English;"), по умолчанию пробелом. Ниже приведённые примеры эквивалентны:

$temp = join($", @ARGV);
system "echo $temp";

system "echo @ARGV";

Внутри шаблонов поиска (которые также подвергаются подстановке с двойными кавычками) существует неустранимая двусмысленность: интерпретируется ли /$foo[bar]/ как /${foo}[bar]/ (где [bar] — класс символов для регулярного выражения) или как /${foo[bar]}/ (где [bar] — индекс массива @foo)? Если @foo не существует иначе, то это, очевидно, класс символов. Если @foo существует, Perl делает предположение о [bar], и почти всегда верно. Если он ошибётся или вы просто параноик, вы можете принудительно задать правильную интерпретацию с помощью фигурных скобок, как описано выше.

Если вам нужна информация о том, как использовать здесь-документы, которая раньше находилась здесь, она переместилась в "Quote and Quote-like Operators" в perlop.

Конструкторы списков значений

Значения списков обозначаются разделением отдельных значений запятыми (и заключением списка в скобки, если это требуется для приоритета):

(LIST)

В контексте, не требующем значения списка, значение того, что похоже на литерал списка, просто значение последнего элемента, как в операторе запятой C. Например,

@foo = ('cc', '-E', $bar);

присваивает всё значение списка массиву @foo, но

$foo = ('cc', '-E', $bar);

присваивает значение переменной $bar скалярной переменной $foo. Обратите внимание, что значение фактического массива в скалярном контексте — это длина массива; следующее присваивает значение 3 переменной $foo:

@foo = ('cc', '-E', $bar);
$foo = @foo;                # $foo gets 3

Вы можете иметь необязательную запятую перед закрывающей скобкой литерала списка, чтобы вы могли сказать:

@foo = (
    1,
    2,
    3,
);

Чтобы использовать здесь-документ для присвоения массива, по одной строке на элемент, вы можете использовать подход, подобный этому:

@sauces = <<End_Lines =~ m/(\S.*\S)/g;
    normal tomato
    spicy tomato
    green chile
    pesto
    white wine
End_Lines

СПИСКИ выполняют автоматическую интерполяцию подсписков. То есть, когда оценивается СПИСОК, каждый элемент списка оценивается в контексте списка, и результирующее значение списка интерполируется в СПИСОК так, как будто каждый отдельный элемент был членом СПИСКА. Таким образом, массивы и хэши теряют свою идентичность в СПИСКЕ — список

(@foo,@bar,&SomeSub,%glarch)

содержит все элементы @foo, за которыми следуют все элементы @bar, за которыми следуют все элементы, возвращённые подпрограммой с именем SomeSub, вызываемой в контексте списка, за которыми следуют пары ключ/значение %glarch. Чтобы создать ссылку на список, который НЕ выполняет интерполяцию, см. perlref.

Пустой список представлен (). Интерполяция его в список не оказывает никакого эффекта. Таким образом, ((),(),()) эквивалентно (). Аналогично, интерполяция массива без элементов такая же, как если бы этот массив не был интерполирован в этом месте.

Эта интерполяция сочетается с тем фактом, что открывающие и закрывающие скобки необязательны (за исключением случаев, когда это необходимо для приоритета), и списки могут заканчиваться необязательной запятой, что означает, что несколько запятых в списках являются допустимым синтаксисом. Список 1,,3 является конкатенацией двух списков, 1, и 3, первый из которых заканчивается этой необязательной запятой. 1,,3 это (1,),(3) это 1,3 (И аналогично для 1,,,3 это (1,),(,),3 это 1,3 и так далее.) Не будем советовать вам использовать такую обфускацию.

Значение списка также может быть индексированным, как обычный массив. Вы должны поместить список в скобки, чтобы избежать неоднозначности. Например:

# Stat returns list value.
$time = (stat($file))[8];

# SYNTAX ERROR HERE.
$time = stat($file)[8];  # OOPS, FORGOT PARENTHESES

# Find a hex digit.
$hexdigit = ('a','b','c','d','e','f')[$digit-10];

# A "reverse comma operator".
return (pop(@foo),pop(@foo))[0];

Списки можно присваивать только тогда, когда каждый элемент списка сам по себе допустим для присвоения:

($x, $y, $z) = (1, 2, 3);

($map{'red'}, $map{'blue'}, $map{'green'}) = (0x00f, 0x0f0, 0xf00);

Исключением из этого является то, что вы можете присвоить undef в списке. Это полезно для отбрасывания некоторых возвращаемых значений функции:

($dev, $ino, undef, undef, $uid, $gid) = stat($file);

Начиная с Perl 5.22, вы также можете использовать (undef)x2 вместо undef, undef. (Вы также можете сделать ($x) x 2, что менее полезно, так как оно присваивает одной и той же переменной дважды, перезаписывая первое присвоенное значение.)

При присвоении списка скаляров массиву все предыдущие значения в этом массиве стираются, и количество элементов в массиве теперь будет равно количеству элементов в правом списке — списке, из которого происходило присвоение. Массив автоматически изменит свой размер, чтобы точно вместить каждый элемент правого списка.

use warnings;
my (@xyz, $x, $y, $z);

@xyz = (1, 2, 3);
print "@xyz\n";                             # 1 2 3

@xyz = ('al', 'be', 'ga', 'de');
print "@xyz\n";                             # al be ga de

@xyz = (101, 102);
print "@xyz\n";                             # 101 102

Однако, когда вы присваиваете список скаляров другому списку скаляров, результаты различаются в зависимости от того, имеет ли левый список — список, которому присваивается — такое же, больше или меньше элементов, чем правый список.

($x, $y, $z) = (1, 2, 3);
print "$x $y $z\n";                         # 1 2 3

($x, $y, $z) = ('al', 'be', 'ga', 'de');
print "$x $y $z\n";                         # al be ga

($x, $y, $z) = (101, 102);
print "$x $y $z\n";                         # 101 102
# Use of uninitialized value $z in concatenation (.)
# or string at [program] line [line number].

Если число скаляров в левом списке меньше, чем в правом, «лишние» скаляры в правом списке просто не будут присвоены.

Если число скаляров в левом списке больше, чем в правом, «пропущенные» скаляры станут неопределёнными.

($x, $y, $z) = (101, 102);
for my $el ($x, $y, $z) {
    (defined $el) ? print "$el " : print "<undef>";
}
print "\n";
                                            # 101 102 <undef>

Присвоение списка в скалярном контексте возвращает количество элементов, полученных выражением в правой части присваивания:

$x = (($foo,$bar) = (3,2,1));       # set $x to 3, not 2
$x = (($foo,$bar) = f());           # set $x to f()'s return count

Это удобно, когда вы хотите выполнить присвоение списка в булевом контексте, потому что большинство функций списка возвращают пустой список по завершении, который, при присвоении, даёт 0, который интерпретируется как ЛОЖЬ.

Это также источник полезного идиомы для выполнения функции или операции в контексте списка, а затем подсчёта количества возвращаемых значений, путём присваивания пустому списку, а затем использования этого присваивания в скалярном контексте. Например, этот код:

$count = () = $string =~ /\d+/g;

поместит в $count количество групп цифр, найденных в $string. Это происходит потому, что соответствие шаблону находится в контексте списка (так как оно присваивается пустому списку) и, следовательно, вернёт список всех соответствующих частей строки. Присвоение списка в скалярном контексте переведёт это в количество элементов (здесь — количество раз, когда шаблон соответствовал) и присвоит это $count. Обратите внимание, что простое использование

$count = $string =~ /\d+/g;

не сработало бы, так как соответствие шаблону в скалярном контексте вернёт только true или false, а не счёт совпадений.

Последний элемент присвоения списка может быть массивом или хэш-таблицей:

($x, $y, @rest) = split;
my($x, $y, %rest) = @_;

Вы можете фактически поместить массив или хэш-таблицу в любой части списка, но первый из них в списке поглотит все значения, а всё после него станет неопределённым. Это может быть полезно в операторах my() или local().

Хэш-таблица может быть инициализирована с помощью литерального списка, содержащего пары элементов, которые интерпретируются как ключ и значение:

# same as map assignment above
%map = ('red',0x00f,'blue',0x0f0,'green',0xf00);

Хотя литеральные списки и именованные массивы часто взаимозаменяемы, это не относится к хэш-таблицам. Просто потому, что вы можете индексировать значение списка, как это делает обычный массив, не означает, что вы можете индексировать значение списка как хэш-таблицу. Аналогично, хэш-таблицы, включённые как части других списков (включая списки параметров и списки возвращаемых значений функций), всегда сжимаются в пары ключ/значение. Вот почему иногда полезно использовать ссылки.

Часто более читаемо использовать оператор => между парами ключ/значение. Оператор => в основном является визуально отличным синонимом запятой, но он также обеспечивает интерпретацию левого операнда как строки, если это «голое слово», которое будет допустимым простым идентификатором. => не приводит к экранированию составных идентификаторов, содержащих двойные двоеточия. Это делает его удобным для инициализации хэш-таблиц:

 %map = (
              red   => 0x00f,
              blue  => 0x0f0,
              green => 0xf00,
);

или для инициализации ссылок на хэш-таблицы для использования в качестве записей:

$rec = {
            witch => 'Mable the Merciless',
            cat   => 'Fluffy the Ferocious',
            date  => '10/31/1776',
};

или для использования вызова по именованому параметру для сложных функций:

$field = $query->radio_group(
            name      => 'group_name',
            values    => ['eenie','meenie','minie'],
            default   => 'meenie',
            linebreak => 'true',
            labels    => \%labels
);

Обратите внимание, что просто потому, что хэш-таблица инициализируется в таком порядке, не означает, что она выводится в таком же порядке. См. "sort" в perlfunc для примеров того, как обеспечить порядок вывода.

Если ключ появляется более одного раза в списке инициализаторов хэш-таблицы, последнее вхождение имеет приоритет:

%circle = (
              center => [5, 10],
              center => [27, 9],
              radius => 100,
              color => [0xDF, 0xFF, 0x00],
              radius => 54,
);

# same as
%circle = (
              center => [27, 9],
              color => [0xDF, 0xFF, 0x00],
              radius => 54,
);

Это может использоваться для предоставления настраиваемых значений по умолчанию:

# values in %args take priority over %config_defaults
%config = (%config_defaults, %args);

Индексы

Массив можно получить по одному скаляру за раз, указав знак доллара ($), затем имя массива (без ведущего @), а затем индекс в квадратных скобках. Например:

@myarray = (5, 50, 500, 5000);
print "The Third Element is", $myarray[2], "\n";

Индексы массива начинаются с 0. Отрицательный индекс получает значение с конца. В нашем примере $myarray[-1] было бы 5000, а $myarray[-2] — 500.

Индексирование хэш-таблиц аналогично, только вместо квадратных скобок используются фигурные скобки. Например:

%scientists = 
(
    "Newton" => "Isaac",
    "Einstein" => "Albert",
    "Darwin" => "Charles",
    "Feynman" => "Richard",
);

print "Darwin's First Name is ", $scientists{"Darwin"}, "\n";

Вы также можете индексировать список, чтобы получить один элемент из него:

$dir = (getpwnam("daemon"))[7];

Эмуляция многомерных массивов

Многомерные массивы могут быть эмулированы индексированием хэш-таблицы списком. Элементы списка соединяются с разделителем индексов (см. "$;" в perlvar).

$foo{$x,$y,$z}

эквивалентно

$foo{join($;, $x, $y, $z)}

По умолчанию разделителем индексов является "\034", такой же, как SUBSEP в awk.

Срезы

Срез получает доступ к нескольким элементам списка, массива или хэш-таблицы одновременно, используя список индексов. Это удобнее, чем писать отдельные элементы как список отдельных скалярных значений.

($him, $her)   = @folks[0,-1];              # array slice
@them          = @folks[0 .. 3];            # array slice
($who, $home)  = @ENV{"USER", "HOME"};      # hash slice
($uid, $dir)   = (getpwnam("daemon"))[2,7]; # list slice

Так как вы можете присваивать списку переменных, вы также можете присваивать массиву или хэш-срез.

@days[3..5]    = qw/Wed Thu Fri/;
@colors{'red','blue','green'} 
               = (0xff0000, 0x0000ff, 0x00ff00);
@folks[0, -1]  = @folks[-1, 0];

Предыдущие присваивания точно эквивалентны

($days[3], $days[4], $days[5]) = qw/Wed Thu Fri/;
($colors{'red'}, $colors{'blue'}, $colors{'green'})
               = (0xff0000, 0x0000ff, 0x00ff00);
($folks[0], $folks[-1]) = ($folks[-1], $folks[0]);

Так как изменение среза изменяет исходный массив или хэш-таблицу, которую он срезает, конструкция foreach изменит некоторые — или даже все — значения массива или хэш-таблицы.

foreach (@array[ 4 .. 10 ]) { s/peter/paul/ } 

foreach (@hash{qw[key1 key2]}) {
    s/^\s+//;                       # trim leading whitespace
    s/\s+$//;                       # trim trailing whitespace
    s/\b(\w)(\w*)\b/\u$1\L$2/g;     # "titlecase" words
}

Как специальное исключение, когда вы срезаете список (но не массив или хэш-таблицу), если список оценивается как пустой, то взятие среза этого пустого списка всегда возвращает пустой список. Таким образом:

@a = ()[0,1];          # @a has no elements
@b = (@a)[0,1];        # @b has no elements
@c = (sub{}->())[0,1]; # @c has no elements
@d = ('a','b')[0,1];   # @d has two elements
@e = (@d)[0,1,8,9];    # @e has four elements
@f = (@d)[8,9];        # @f has two elements

Это облегчает написание циклов, которые завершаются при возвращении пустого списка:

while ( ($home, $user) = (getpwent)[7,0] ) {
    printf "%-8s %s\n", $user, $home;
}

Как отмечалось ранее в этом документе, скалярное значение присвоения списка — это количество элементов в правой части присвоения. Пустой список не содержит элементов, поэтому, когда файл паролей исчерпан, результатом является 0, а не 2.

Срезы в скалярном контексте возвращают последний элемент среза.

@a = qw/first second third/;
%h = (first => 'A', second => 'B');
$t = @a[0, 1];                  # $t is now 'second'
$u = @h{'first', 'second'};     # $u is now 'B'

Если вы запутались, почему вы используете '@' там для среза хэш-таблицы вместо '%', подумайте об этом так. Тип скобки (квадратные или фигурные) определяет, массив или хэш-таблица рассматриваются. С другой стороны, ведущий символ ('$' или '@') для массива или хэш-таблицы указывает, возвращается ли одно значение (скаляр) или несколько (список).

Срезы хэш-таблицы ключ/значение

Начиная с Perl 5.20, операция среза хэш-таблицы с символом % является вариантом операции среза, возвращающей список пар ключ/значение, а не только значений:

%h = (blonk => 2, foo => 3, squink => 5, bar => 8);
%subset = %h{'foo', 'bar'}; # key/value hash slice
# %subset is now (foo => 3, bar => 8)
%removed = delete %h{'foo', 'bar'};
# %removed is now (foo => 3, bar => 8)
# %h is now (blonk => 2, squink => 5)

Однако, результат такого среза не может быть локализован или присвоен. В остальном они очень похожи на срезы хэш-таблицы с использованием символа @.

Срезы массива индекс/значение

Аналогично срезам хэш-таблицы ключ/значение (также представленным в Perl 5.20), синтаксис среза массива % возвращает список пар индекс/значение:

@a = "a".."z";
@list = %a[3,4,6];
# @list is now (3, "d", 4, "e", 6, "g")
@removed = delete %a[3,4,6]
# @removed is now (3, "d", 4, "e", 6, "g")
# @list[3,4,6] are now undef

Обратите внимание, что вызов delete для значений массива строго не рекомендуется.

Типглобы и дескрипторы файлов

Perl использует внутренний тип, называемый типглобом, для хранения всей записи таблицы символов. Префикс типа типглоба — *, поскольку он представляет все типы. Раньше это был предпочтительный способ передачи массивов и хэш-таблиц по ссылке в функцию, но теперь, когда у нас есть реальные ссылки, это редко требуется.

Основное использование типглобов в современном Perl — это создание псевдонимов таблицы символов. Это присваивание:

*this = *that;

делает $this псевдонимом $that, @this псевдонимом @that, %this псевдонимом %that, &this псевдонимом &that и т. д. Гораздо безопаснее использовать ссылку. Это:

local *Here::blue = \$There::green;

временно делает $Here::blue псевдонимом $There::green, но не делает @Here::blue псевдонимом @There::green или %Here::blue псевдонимом %There::green и т. д. См. "Таблицы символов" в perlmod для получения дополнительных примеров этого. Как бы странно это ни выглядело, это основа всей системы импорта/экспорта модулей.

Ещё одно использование типглобов — передача дескрипторов файлов в функцию или создание новых дескрипторов файлов. Если вам нужно использовать типглоб для сохранения дескриптора файла, сделайте это так:

$fh = *STDOUT;

или, возможно, как реальная ссылка, например, так:

$fh = \*STDOUT;

См. perlsub для примеров использования этих значений в качестве косвенных дескрипторов файлов в функциях.

Типглобы также являются способом создания локального дескриптора файла с помощью оператора local(). Они существуют до выхода из своего блока, но могут быть переданы обратно. Например:

sub newopen {
    my $path = shift;
    local  *FH;  # not my!
    open   (FH, $path)          or  return undef;
    return *FH;
}
$fh = newopen('/etc/passwd');

Теперь, когда у нас есть *foo{THING} обозначение, типглобы не так часто используются для манипуляций с дескрипторами файлов, хотя они всё ещё необходимы для передачи новых дескрипторов файлов и каталогов в функции или из функций. Это потому, что *HANDLE{IO} работает только в том случае, если HANDLE уже использовался в качестве дескриптора. Другими словами, *FH необходимо для создания новых записей в таблице символов; *foo{THING} не может этого сделать. В случае сомнений используйте *FH.

Все функции, способные создавать дескрипторы файлов (open(), opendir(), pipe(), socketpair(), sysopen(), socket(), и accept()), автоматически создают анонимный дескриптор файла, если переданный им дескриптор — это неинициализированная скалярная переменная. Это позволяет использовать конструкции, такие как open(my $fh, ...) и open(local $fh,...), для создания дескрипторов файлов, которые будут удобно закрыты автоматически при выходе из области видимости, если нет других ссылок на них. Это в значительной степени устраняет необходимость в типглобах при открытии дескрипторов файлов, которые должны передаваться, как в следующем примере:

sub myopen {
    open my $fh, "@_"
         or die "Can't open '@_': $!";
    return $fh;
}

{
    my $f = myopen("</etc/motd");
    print <$f>;
    # $f implicitly closed here
}

Обратите внимание, что если вместо этого используется инициализированная скалярная переменная, результат отличается: my $fh='zzz'; open($fh, ...) эквивалентно open( *{'zzz'}, ...). use strict 'refs' запрещает такую практику.

Другой способ создания анонимных дескрипторов файлов — использование модуля Symbol или модуля IO::Handle и ему подобных. Эти модули имеют преимущество в том, что не скрывают различные типы одного и того же имени во время использования local(). См. конец "open" в perlfunc для примера.

ДРУГОЕ

См. perlvar для описания встроенных переменных Perl и обсуждения допустимых имён переменных. См. perlref, perlsub и "Таблицы символов" в perlmod для более подробного обсуждения типглобов и *foo{THING} синтаксиса.

© 1993–2021 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.36.0/perldata

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API