Некоторые сведения о Perl 5/Типы данных
Глава | Операции и выражения → | |
Типы данных | ||
В языке Perl всего три основных типа данных:
- Скаляр. Предназначен для представления и обработки чисел и последовательностей символов (строк).
- Массив скаляров. Предназначен для хранения и обработки нескольких скалярных данных, доступ к которым осуществляется по индексам.
- Ассоциативный массив скаляров (иногда называемый хешем). Предназначен для создания различных динамических структур: списки, деревья и прочее.
Перечисленные типы данных мы рассмотрим в этой главе. Кроме них есть еще и другие типы (например функция может рассматриваться как тип данных), но мы будем рассматривать их в более поздних главах, чтобы не перегружать читателя.
Скаляры
[править]Скаляры позволяют хранить и обрабатывать числовые и строковые литералы. Числовые литералы могут быть записаны в десятичной, восьмеричной и шестнадцатеричной форме. В свою очередь, десятичные числа могут быть записаны в целой или вещественной форме. Вот несколько примеров числовых литералов, которые могут быть присвоены скалярам.
25 # Целое число
64.567 # Вещественное число
0.546 # Вещественное число с нулевой целой частью
.546 # Несущественные нули допустимо опускать
# В языке Perl для больших чисел разряды можно отделять друг от друга символом нижнего подчеркивания
# для улучшения читаемости кода.
5465249.682 # Так, следующий числовой литерал может быть записан
5_465_249.682
# Восьмеричные и шестнадцатеричные числа
021 # в десятеричной системе 17. Ведущий ноль указывает на восьмеричную систему счисления
# Шестнадцатеричные числа всегда начинаются на префикс "0x", причем использовать "0X" НЕЛЬЗЯ.
# Буквы A-F могут быть записаны в любом регистре.
0xAB3
0xf
Вещественные числа с плавающей точкой могут быть записаны в экспоненциальной форме:
# [цифры].[цифры][E|e][+|-][цифры]
# <мантисса> E <экспонента>
12.567E12
12.567E+04
1e-85
1E+12
Хотя внешне кажется, что целые и вещественные числа это что-то разное, внутри Perl все числа представляются в формате чисел с плавающей точкой удвоенной точности. Это означает, что экспонента должна быть в пределах -323 до +308, а мантисса может иметь не более 16 значащих цифр. При выходе за этот диапазон скаляру будет присвоено 0 в меньшем пределе и специальный символ 1.#INF
— в большем пределе, означающем бесконечно большое число.
Строковые литералы должны всегда ограничиваться одинарными ('
), двойными ("
) или обратными (`
) кавычками. В строковых литералах, ограниченных одинарными кавычками, нельзя использовать управляющие последовательности или экранирование, кроме двух: \'
(отображает одинарную кавычку) и \\
(отображает обратный слеш). Другими словами, одинарные кавычки используются, когда все символы в литерале нужно понимать буквально. Двойные кавычки используются, когда управляющие последовательности должны быть переданы устройству вывода, например для переноса строки или табуляции.
Литералы в обратных кавычках используются подобно тому, как это делается в сценариях командных оболочек, т.е. они называют программу, которая должна быть выполнена, а ее вывод должен быть подставлен как большой литерал. Точно такой же способ подстановки вывода есть в командной оболочке Bourne Shell и всех ее производных.
'Very long string\n' # Строковый литерал. В нем управляющая последовательность '\n' не будет интерпретироваться
"\tVery long string\n" # Две управляющие последовательности будут переданы на устройство вывода, т.е. текст выведется
# с отступом и в конце будет перенос на новую строку
'Каталога \'~john/docs\' не существует' # Мы используем одинарные кавычки в литерале, чтобы подчеркнуть путь.
'Диск E:\\ переполнен' # Будет выведено "Диск E:\ переполнен".
`ls` # Литералом будет вывод команды ls.
Разобравшись в том, что можно хранить в скаляре, рассмотрим как он объявляется. Скаляр, как впрочем и любой другой тип, должен быть присвоен переменной, которая будет отсылать нас на некоторый участок памяти. Присваивание скаляра переменной будет в итоге определять ее тип, как переменная, хранящая скаляр. Для обозначения такой переменной в Perl используется символ доллара $
:
$scalar_variable;
$deviceName;
$name_1;
# Здесь $ означает, что переменная хранит скаляр, а идентификатор за ним означает имя переменной.
# В общем случае скаляр может не иметь значения.
Скалярная переменная за один раз может хранить либо число, либо строку, причем не существует способа заранее определить что из этого хранится в скаляре. Это связано с тем, что в Perl существует механизм неявного преобразования, который включается когда со скалярами производятся операции. Например, при арифметической операции над двумя скалярами, Perl сначала попытается преобразовать их в числа. Напротив, при строковой конкатенации оба скаляра должны быть преобразованы в строки. Если Perl по какой-то причине не удается преобразовать значение в контексте операции, то интерпретатором будет генерироваться ошибка.
$price = 15; # Скаляр хранит число
print "Книга стоит $price рублей"; # В контексте данной операции число будет преобразовано в строку
# Если при подстановке скаляра за именем переменной идут символы, которые можно использовать в именах переменных
# (то есть если за подстановкой нет разделителя), нужно поместить имя переменной в фигурные скобки.
$day = 15;
print "January ${day}th"; # January 15th
На практике всегда следует заключать строковые литералы в кавычки, однако это не всегда обязательно. Если интерпретатор Perl обнаружит в программе не закавыченную строку, то он сначала «попытается понять» является ли она ключевым словом Perl. Если слово не является ключевым, то оно будет интерпретировано как строковый литерал.
$day = Friday; # Допустимо
# Однако, без кавычек можно оставлять строковые литералы, которые имеют только буквы латинского алфавита.
Массивы скаляров
[править]Массив скаляров позволяет представить не один скаляр, а сразу несколько, доступ к которым осуществляется по индексам. Для объявления массива используется пара круглых скобок, называемая конструктором массива. Так как скаляр может хранить числа или строки, то с точки зрения Perl массив может хранить смешанные данные.
$day = 15;
("скаляр_1", 156, "скаляр_3", $day) ;
При присваивании массива переменной, перед ее именем используется символ @
, который указывает, что переменная хранит массив скаляров. Чтобы обратиться к скаляру в массиве, используется синтаксис, подобный обращению к скаляру, но за именем переменной в квадратных скобках указывается индекс. Тем самым, язык подчеркивает, что массив хранит скаляры. Элементы в массиве скаляров отсчитываются с нуля.
@array = ("one", 2, "three", 4);
print "Element 0: $array[0]\n"; # Печатаем элемент с индексом 0
print "Element 1: ${array[1]}d\n"; # Печатаем элемент с индексом 1
# Допускается использование отрицательных индексов: в этом случае -1 означает последний элемент,
# -2 – предпоследний и т.д.
print "Element 2: $array[-2]\n";
print "Element 3: $array[-1]\n";
$array[3] = 5; # Изменяем значение с индексом 3
print "Element 3: $array[3]\n";
# Чтобы узнать последний индекс массива, используется такой синтаксис, где
# за символом решетки идет имя массива. Такой прием используется для вычисления его размера.
print "Last index: $#array\n";
$arr2[0] = 51; # Массив также порождается при добавлении в него хотя бы одного значения
print $arr2[0];
Массивы в Perl являются динамическими, т.е. добавление в них новых элементов автоматически увеличивает их размер. Если добавить к массиву элемент, который отстает от последнего элемента на несколько индексов, пустые элементы будут заполняться пустыми строками. В Perl можно обращаться к несуществующим элементам в массиве: в этом случае будет возвращаться пустая строка. В режиме вывода предупреждающих сообщений, при попытке обратиться к несуществующему элементу будет выводиться предупреждение.
Как и скаляры, массивы можно распечатать с помощью print
.
@digits = (1..9); # В данном примере мы сформировали массив через диапазон
print "Digits: @digits\n"; # Когда массив подставляется в другой строковый литерал, его элементы будут перечислены через пробел.
print "@digits\n"; # Или так.
print @digits, "\n"; # Но если оператору он будет передан так, то вывод будет без отделения пробелом.
Результат вывода
Digits: 1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
123456789
Печать элементов массива аналогична печати скаляров, однако здесь следует упомянуть интересную особенность:
$digit = 6;
@digit = (5);
# В Perl такая ситуация не запрещена.
# Что будет здесь напечатано?
print "$digit[0]\n"
# Правильный ответ будет 5, но в таком случае как нам напечатать скаляр $digit при такой конфигурации строки.
# Здесь существует несколько подходов и все они направлены на то, чтобы синтаксис с индексом
# представить как строковый литерал.
# Следующие три вызова напечатают "6[0]".
print "${digit}[0]\n";
print "$digit\[0]\n";
print "$digit" . "[0]\n"; # Оператор . конкатенирует строки
Из любого массива можно выделить подмножество (иногда говорят получить срез массива). Для этого нужно использовать такой синтаксис:
@digits = (1..15);
print "@digits[5,10,14]\n"; # В квадратных скобках через запятую перечисляются индексы элементов, которые мы хотим увидеть в срезе
print "@digits[5..10]\n"; # Диапазон индексов
print "@digits[1,2,5..9,12,13]\n"; # Смешанный подход
Результат
6 11 15
6 7 8 9 10 11
2 3 6 7 8 9 10 13 14
Если присвоить массив скаляру (т.н. выполнение выражения в скалярном контексте), можно узнать его размер:
@arr = (1..5);
$size = @arr;
print "$size\n";
# Результат:
# 5
Ассоциативные массивы скаляров
[править]Ассоциативные массивы используются в Perl для создания сложных структур, когда возможностей простых массивов не хватает. Концептуально ассоциативные массивы отличаются от простых массивов тем, что в них для ссылки на элементы используются ассоциативные ключи. Ассоциативный ключ является строковым литералом. Далее для краткости мы будем говорить хеш-массив, однако имейте в виду, что оба слова равнозначны.
Хеш-массив можно объявить по-разному:
# Хеш-массив создается как простой массив, но теперь необходимо в нечетные элементы
# помещать ассоциативные ключи, которые будут связываться со значениями, идущими за ними.
(key1, value1, key2, value2) ;
# Чтобы подчеркнуть то, что в переменной хранится хеш-массив, используется символ '%'.
%person = (name, "Larry", surname, "Wall");
# Здесь 'name' ассоциативный ключ к скаляру "Larry", а 'surname' — к "Wall".
# Чтобы обратиться к элементу хеш-массива по ключу, используется синтаксис $имя-хеш-массива{"ключ"}.
print "Name: $person{name}\nSurname: $person{surname}\n";
# Создание массива через такой конструктор удобен, когда вы преобразуете обычный массив в хеш-массив.
# В большинстве случаев следующий способ объявления хеш-массива удобнее.
%person = (
name => "Larry",
surname => "Wall"
);
print "Name: $person{name}\nSurname: $person{surname}\n";
В последнем случае оператор =>
аналогичен запятой с той разницей, что левый операнд всегда должен быть строковым литералом. Также обратим внимание, что запятую можно поставить в конце и для второго ключа, и это не будет ошибкой
%person = (
name => "Larry",
surname => "Wall", # запятая здесь не ошибка
);
Для добавления нового элемента в хеш-массив или изменения существующего, достаточно просто обратиться по ключу. Если элемента не было, то он будет создан.
%person = (
name => "Larry",
surname => "Wall"
);
print %person, "\n";
$person{name} = "Garry"; # Значение по существующему ключу будет изменено
$person{phone} = 1234; # Новое значение будет добавлено
print %person, "\n";
delete($person{name}); # Удалить существующий элемент можно с помощью функции delete
print %person, "\n";
Для хеш-массивов существуют две встроенные функции, которые позволяют распечатать либо все ключи, либо все значения в массиве.
%person = (
name => "Larry",
surname => "Wall",
phone => 1234,
);
print keys(%person), "\n"; # Печатает все ключи хеш-массива
print values(%person), "\n"; # Печатает все значения хеш-массива
О переменных
[править]Переменная в Perl не может быть рассмотрена вне контекста типов данных и операций, поэтому в этом разделе мы ограничимся только общими словами.
- Переменная в Perl, как и в любом языке программирования, это именованный участок памяти. Первый символ перед именем переменной определяет ее тип:
$
(скаляр),@
(массив скаляров),%
(хеш-массив). - Имя переменной чувствительно к регистру и может состоять из цифр, букв и символа нижнего подчеркивания и не должно начинаться с цифры, а также не должно совпадать с зарезервированным в Perl словом. В Perl может быть создано три одноименных переменных, каждая из которых хранит по отдельному типу данных, например
$var
,@var
и%var
. Это возможно потому, что интерпретатор хранит имена переменных в разных списках для разных типов. - В выражениях, когда в качестве операнда используется некоторый тип, его интерпретация может зависеть от контекста, в котором он вычисляется, в частности существует два контекста: скалярный и списковый (векторный). Это важно, так как от этого будет зависеть конечный результат выражения. Об этом будет подробно рассказано, когда речь пойдет об операциях.
- Любая переменная может находиться в состоянии определена или не определена. Переменная считается определенной, если ей присвоено какое-то значение. Чтобы определить статус переменной, следует пользоваться встроенной функцией
defined
. - Переменную можно сделать неопределенной, если вызвать функцию
undef
. Вызов этой функции будет приводить к освобождению памяти от ненужных данных. - Любая переменная имеет некоторую видимость относительно других участков программы. Видимость зависит от того, где и как переменная объявлена. Например, в вышеприведенных примерах все переменные были объявлены в глобальной области видимости. Когда переменная выходит из своей области видимости, она уничтожается.
Операции и выражения → |