Язык программирования Perl - Михаил Шохирев
Шрифт:
Интервал:
Закладка:
Разыменование ссылки на элемент хэша также записывается уже знакомым нам способом, когда перед ссылочной переменной ставится префикс скаляра $, а после нее - ключ элемента хэша в фигурных скобках. Ссылочная переменная может заключаться в фигурные скобки:
${$ref2hash}{'ключ'} = 'значение'; # изменение значения print $$ref2hash{'ключ'}; # доступ к значению элемента хэша
В другой форме разыменования ссылки к переменной, содержащей ссылку на хэш, применяется операция "стрелка", после которой в фигурных скобках указывается ключ элемента хэша. Вот так:
$ref2hash->{'термин'} = 'определение'; # добавим элемент $value = $ref2hash->{'Хэш'}; # найдем значение по ключу
Если ссылка используется как ключ хэша, она, как и любой ключ хэша, автоматически преобразуется в строку. Такие строки невозможно применять для доступа к объектам ссылки, но они могут служить отличными уникальными ключами хэша, поскольку строковое значение ссылки содержит адрес объекта в памяти, например, 'SCALAR(0x335b04)' или 'ARRAY(0x334dd8)'. Если все-таки требуется использовать ссылки в качестве ключей хэша, то можно воспользоваться модулем Tie::RefHash.
Аналогично созданию "массива массивов" создаются и другие разновидности ссылочных структур данных: массивы хэшей, хэши массивов и хэши хэшей. Ссылочные структуры применяются для структурированного представления взаимосвязанных данных. Для хранения в каждом элементе массива нескольких значений применяется массив хэшей (Array of Hashes, AoH). Вот пример массива, содержащий ссылки на анонимные хэши, в каждом из которых хранятся сведения о каком-либо объекте:
my $AoH = [ # этапы "Формулы-1" '2006 года {grandprix=>'Бахрейна', date=>'2006.03.12'}, {grandprix=>'Малайзии', date=>'2006.03.19'}, {grandprix=>'Австралии', date=>'2006.04.02'}, {grandprix=>'Сан-Марино', date=>'2006.04.23'}, # и так далее... ]; # напечатать хэш, на который ссылается 4-й элемент массива print "Гран-при $AoH->[3]->{grandprix} $AoH->[3]->{date}"; # выведет: Гран-при Сан-Марино 2006.04.23
Для того чтобы ассоциировать с каждым ключом хэша список скалярных значений, применяется хэш массивов (Нash of Аrrays, HoA). Приведем пример хэша массивов, где в каждом элементе хэша хранится ссылка на анонимный список ассоциированных значений:
my $HoA = { # годы создания языков программирования 1964 => ['SIMULA', 'BASIC', 'PL/1'], 1970 => ['Forth', 'Pascal', 'Prolog'], 1979 => ['Ada', 'Modula-2'], 1987 => ['Perl', 'Haskell', 'Oberon'], 1991 => ['Python', 'Visual Basic'] }; # напечатать список, ассоциированный с 1987 годом foreach my $language (sort @{$HoA->{1987}}) { print "$language "; } # выведет: Haskell Oberon Perl
Элементы хэша также могут хранить ссылки на другие хэши, образуя хэш хэшей (Нash of Нashes, HoH). Вот пример описания хэша хэшей, где с каждым поисковым ключом ассоциируется анонимный хэш с информацией об объекте:
my $HoH = { # авторы и годы создания языков программирования 'Pascal' => {author=>'Niklaus Wirth', year=>1970}, 'Perl' => {year=>1987, author=>'Larry Wall'}, 'C' => {author=>'Dennis Ritchie', year=>1972} }; # в каком году был создан Pascal? print $HoH->{'Pascal'}->{'year'}; # выведет: 1970 # кто создал язык Си? print $HoH->{'C'}->{'author'}; # выведет: Dennis Ritchie
Имеющиеся в других языках программирования записи (record) или структуры (struct), в Perl чаще всего представляются в виде хэшей, в которых ключи используются в качестве имен полей и применяются для доступа к значениям полей записи. Для завершающего примера создадим набор записей с информацией о людях. Каждая запись будет анонимным хэшем, а ссылки на записи будут храниться в массиве. В каждой записи дату рождения представим в виде анонимного массива, содержащего год, месяц и день. Вот таким образом:
my $family = [ # массив записей о семье {name => 'Михаил', birthday => [1958, 11, 12]}, {name => 'Ирина', birthday => [1955, 03, 23]}, {name => 'Маша', birthday => [1980, 07, 27]}, {name => 'Миша', birthday => [1981, 11, 28]}, {name => 'Лев', birthday => [1988, 06, 24]} ]; # напечатаем год рождения Маши: print "$family->[2]->{birthday}->[0]"; # или проще: print "$family->[2]{birthday}[0]"; # выведет: 1980
Подобные структуры легко динамически модифицировать при выполнении программы. Например, добавим в каждую запись новое поле - 'address', в котором сохраним ссылку на запись о месте проживания человека. Адрес оформим в виде анонимного хэша из нескольких полей:
# адрес в виде анонимного хэша, в $address - ссылка на него: $address = {country => 'Россия', index => 641870}; # и т.д. # добавить поле адреса и поместить туда $address: foreach my $person (@{$family}) { # пропишем всех $person->{address} = $address; # по одному адресу } # выведем почтовый индекс для Ирины print "$family->[1]->{address}->{index}n"; # 641870
На рис. 11.5 приведена ссылочная структура данных, которая получилась в результате выполнения программы. Для доступа по ссылкам ко всем элементам этой структуры используется единственная именованная переменная $family.
Рис. 11.5. Пример ссылочной структуры данных
С помощью ссылок создаются и другие динамические структуры данных: связные списки, деревья и графы. Подытоживая все сказанное о ссылках, в таблице 11.1 приводится сводная информация о синтаксических конструкциях при работе со ссылками.
Таблица 11.1. Синтаксические конструкции для работы со ссылками на данныеСкалярМассивХэшВзятие ссылки на объект$sref = $scalar;$aref = @array;$href = %hash;Создание ссылки на анонимный объект$sref = 'Литерал';$aref = [$a, $b];$href = {$a => $b};Доступ к значению объекта ссылки${$sref} [email protected]{$aref} @$aref%{$href} %$hrefДоступ к значению элемента объекта ссылки$aref-> [$index] ${$aref}[$index]$href->{$key} ${$href}{$key}Доступ к срезу объекта ссылки@{$aref}[$i1, $i2]@{$href}{$k1, $k2}Значение функции ref($ref) для объекта ссылкиSCALARARRAYHASH
Программирующие на Perl на каждом шагу пользуются интерполяцией в строках скалярных переменных и массивов. Иногда требуется включить в строку результат вычисления какого-либо выражения. С помощью ссылок можно интерполировать любое выражение, например, вызов функции. Чтобы включить в строку значение скалярного выражения, его надо заключить в круглые скобки и взять на него ссылку операцией , а затем разыменовать ссылочное выражение как скаляр с помощью префикса $. Вот таким образом:
$s = "localtime() ${($x=localtime)} в скалярном контексте"; # значение выражения, например: 'Sun Mar 26 20:17:36 2006'
Чтобы включить в строку значение выражения, возвращающего список, его надо заключить в квадратные скобки, организуя ссылку на анонимный массив, а потом разыменовать ссылочное выражение как массив с помощью префикса @. Вот так:
$a = "localtime() @{[localtime()]} в списочном контексте"; # значение выражения, например: '36 17 20 26 2 106 0 84 1'
Ссылки, о которых до этого шла речь, называются жесткими ссылками. Жесткая ссылка (hard reference) - это программный объект, хранящий в памяти адрес референта и тип его значения. В Perl имеется еще одна разновидность ссылок, называемых символическими ссылками. Символическая ссылка (symbolic reference) - это строковое значение, которое хранится в скалярной переменной и представляет из себя имя глобальной переменной:
$referent1 = 'Референт'; # объект ссылки $symlink = 'referent' . 1; # символическая ссылка # доступ по символической ссылке к значению объекта print ${$symlink}; # будет выведено: 'Референт'
Символические ссылки используются значительно реже и бывают нужны, когда требуется во время выполнения программы программно создавать имена переменных в виде строк, чтобы затем получать доступ к их значениям. Использование символических ссылок может приводить к трудно обнаруживаемым ошибкам, поэтому лучше запрещать использование в программе символических ссылок с помощью прагмы use strict 'refs'.
В этой лекции изучены ссылки и средства построения с помощью ссылок динамических структур данных. Ссылки дают программисту мощные и гибкие средства доступа к программным объектам. Поэтому многие механизмы работы с данными в Perl организованы с использованием ссылок, и мы будем обращаться к ссылкам в следующих лекциях при изучении подпрограмм, библиотечных модулей и объектного программирования.
Лекция 12. Подпрограммы
В этой лекции будут изучены подпрограммы - единицы структурирования программного кода на Perl, которые также имеют свои особенности: в формах определения и вызова, в способах передачи и обработки параметров, в вариантах возврата значений. Кроме того, в этой лекции будут рассмотрены принципы определения видимости имен переменных в Perl-программе.