Spec-Zone.ru › Perl 5.32

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, а противоположное — случаи, работающие в предыдущих версиях, но не определённые здесь, — вероятно, не будут работать в более новых версиях. Важно отметить, что следующее относится только к идентификаторам «голых слов» в исходном коде 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. Аналогично вышесказанному, знак, за которым следует текст «голого слова» в фигурных скобках, где первый символ — знак возведения в степень. Следующий символ — любой из символов [][A-Z^_?\], за которым следуют символы ASCII слова. Пример: ${^GLOBAL_PHASE}.

  5. Знак, за которым следует любой одиночный символ в диапазоне [\xA1-\xAC\xAE-\xFF] при отсутствии "use utf8". (При "use utf8", применяются обычные правила идентификаторов, приведённые ранее в этом разделе.) Использование неграфических символов (управляющие символы C1, ПРОБЕЛ NO-BREAK и МЯГКИЙ ДЕФИС) запрещено с версии v5.26.0. Использование других символов нежелательно, так как они все зарезервированы для специального значения в Perl, и ни один из них в настоящее время не имеет специального значения, хотя это может измениться без предварительного уведомления.

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

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

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

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

Контекст

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

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

int( <STDIN> )

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

sort( <STDIN> )

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

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

Когда вы используете директиву use warnings или командную строку 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. Однако это не длина массива; это индекс последнего элемента, который имеет другое значение, так как обычно есть 0-й элемент. Присваивание $#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)
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";

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

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

Специальные значения с плавающей точкой: бесконечность (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.

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

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

Слова-несущие значения

Слово, которое не имеет другого толкования в грамматике, будет обрабатываться как строка в кавычках. Они известны как «слова-несущие значения». Как и файловые дескрипторы и метки, слово-несущее значение, состоящее целиком из строчных букв, рискует столкнуться с будущими ключевыми словами, и если вы используете use warnings pragma или переключатель -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], и почти всегда это предположение верно. Если предположение оказывается неверным, или если вы просто параноик, вы можете принудительно установить правильную интерпретацию с помощью фигурных скобок, как описано выше.

Если вы ищете информацию о том, как использовать here-документы, которые раньше были здесь, то она переместилась в "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,
);

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

@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;

не сработало бы, так как соответствие шаблону в скалярном контексте вернет только ИСТИНА или ЛОЖЬ, а не количество совпадений.

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

($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/(\w+)/\u\L$1/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.

END_OF_DOCUMENT_MARKER

Все функции, способные создавать дескрипторы файлов (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–2020 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.32.0/perldata

Spec-Zone.ru

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