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} $$sref | @{$aref} @$aref | %{$href} %$href |
Доступ к значению элемента объекта ссылки | | $aref-> [$index] ${$aref}[$index] | $href->{$key} ${$href}{$key} |
Доступ к срезу объекта ссылки | | @{$aref}[$i1, $i2] | @{$href}{$k1, $k2} |
Значение функции ref($ref) для объекта ссылки | SCALAR | ARRAY | HASH |
Программирующие на 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 = 'Референт'; # объект ссылки