Глава 11 Ссылки и записи

Ссылки и записи

Введение

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

Ссылки

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

Reference      Ox83c6c Referent
ARRAY (Ox83c6c)     (3, 1 is a magic number')

Рис.11.1. Ссылка и субъект


Субъекты в Perl типизованы. Это означает, что ссылку на массив нельзя интерпретировать как ссылку на хэш. При подобных попытках инициируется исключение. В Perl не предусмотрен механизм преобразования типов, и это было сделано намеренно. На первый взгляд кажется, что ссылка - обычный адрес с сильной типизацией. На самом деле это нечто большее. Perl берет на себя автоматическое выделение и освобождение памяти (сборку мусора) для ссылок так же, как и для всего остального. С каждым блоком па Освобожденная память передается Perl для последующего использования, но лишь немногие операционные системы возвращают ее себе. Это связано с тем, что в большинстве схем распределения памяти используется стек, а при освобождении памяти в середине стека опе Чтобы перейти от ссылки к субъекту, снабдите ссылку символом типа для тех данных, к которым вы обращаетесь. Например, если $sref является ссылкой на скалярную величину, возможна следующая запись:
print $$sref; # Выводится скалярная величина, на которую ссылается     $sref $$sref =3; # Присваивается субъекту $sref


Для обращения к отдельному элементу массива или хэша, на который у вас имеется ссылка, используется ассоциативный оператор, оператор -> ("стрелка") - например, $rv->[37] или $rv->{"wilma"}. Помимо разыменования ссылок на массивы и хэши, стрелка та Приведенный выше пример с $$sref можно переписать в виде:
print ${$sref}; # Выводится скалярная величина, на которую ссылается
$sref ${$sref} =3; # Присваивается субъекту $sref
Некоторые программисты для уверенности используют только эту форму. Функция ref получает ссылку и возвращает строку с описанием субъекта. Стро ка обычно принимает одно из значений SCALAR, ARRAY, HASH или CODE, хотя иног-да встречаются и другие встроенные Ссылки в Perl можно создавать для субъектов уже определенных или определяемых с помощью конструкций [ ], { } или sub { }. Использовать оператор \ очень просто: поставьте его перед субъектом, для которого создается ссылка. Например, ссылка на содержимое ма
$rv = \@array;


Создавать ссылки можно даже для констант; при попытке изменить значенш субъекта происходит ошибка времени выполнения:
$р1 = \3.14159;

$$pi =4; # Ошибка

Анонимные данные

Ссылки на существующие данные часто применяются для передачи аргументов функции, но в динамическом программировании они бывают неудобны. Иногда ситуация требует создания нового массива, хэша, скалярной величины или функции, но вам не хочется возиться с им Анонимные массивы и хэши в Perl могут создаваться явно. При этом выделяется память для нового массива или хэша и возвращается ссылка на нее:
$aref = [ 3, 4, 5 ]; # Новый анонимный массив
$href = { "How" => "Now", "Brown" => "Cow" }; # Новый анонимный хэш
В Perl также существует возможность косвенного создания анонимных субъектов. Если попытаться присвоить значение через неопределенную ссылку, Perl автоматически создаст субъект, который вы пытаетесь использовать.
undef $aref;
@$aref = (1, 2, 3);
print $aref;
ARRAY(Ox80c04fO)
Обратите внимание: от undef мы переходим к ссылке на массив, не выполняя фактического присваивания. Perl автоматически создает субъект неопределенной ссылки. Благодаря этому свойству программа может начинаться так:
$а[4][23][53][21] = "fred";
print $a[4][23][53][21];
fred print $a[4][23][53];
ARRAY(Ox81e2494) print $a[4][23];
ARRAY(Ox81e0748) print $a[4];
ARRAY(Ox822cd40)


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

Скалярная величина Массив Хэш Функция

\$scalar \@аггау \%hash \&function

\do{my $anon} { СПИСОК } { СПИСОК } sub { КОД }

Отличия именованных субъектов от анонимных поясняются на приведенных далее рисунках. На рис. 11.2 изображены именованные субъекты, а на рис. 11.3 - анонимные. Иначе говоря, в результате присваивания $а = \$Ь переменные $$а и $Ь занимают одну и ту же область памяти. Если вы напишете $$а = 3, значение $Ь станет равно 3.

Initial state:

©—

$a=\$b;

®—

$$а=3;

®—

print "$$a $b\n 3 3

0х305108

 

 

Ox3051f00

—© —® —®

 

 

5

0х305108

Ox3051f00

SCALAR Ox351f00

5

0х305108

Ox3051f00

SCALAR Ox351f00

5

;

 

 


Рис. 11.2. Именованные субъекты
Все ссылки по определению оцениваются как true, поэтому, если ваша функция возвращает ссылку, в случае ошибки можно вернуть undef и проверить возвращаемое значение следующим образом:
$op_cit = cite($ibid) or die "couldn't make a reference"

Initial state:

®—

$$а=3;

®—

print "$$a $b\n 3 3

0х305108

 

 

Ox3051f00

•*--- (made by Perl)

 

 

0х305108

SCALAR Ox351f00

3

:

 

 


Рис. 11.3. Анонимные субъекты
Оператор undef может использоваться с любой переменной или функцией Perl для освобождения занимаемой ей памяти. Однако не следует полагать, что при вызове undef всегда освобождается память, вызываются деструкторы объектов и т. д. В действительности операт

Записи

Ссылки традиционно применялись в Perl для обхода ограничения, согласно которому массивы и хэши могут содержать только скаляры. Ссылки являются скалярами, поэтому для создания массива массивов следует создать массив ссылок на массивы. Аналогично, хэши хэше массивы хэшей - как массивы ссылок на хэши; хэши массивов - как хэши ссылок на массивы и т. д. Имея в своем распоряжении эти сложные структуры, можно воспользоваться ими для реализации записей. Запись представляет собой отдельную логическую единицу, состоящую из различных атрибутов. Например, запись, описывающая человека, может содержать имя, адрес Наиболее распространенный подход в Perl заключается в том, чтобы интерпретировать хэш как запись, где ключи хэша представляют собой имена полей записи, а ассоциированные величины - значения этих полей. Например, запись "человек" может выглядеть так:
$Nat = { "Name" => "Leonhard Euler",
"Address" => "1729 Ramanujan Lane\nMathworld, PI 31416",
"Birthday" => Ox5bb5580,

Поскольку ссылка $NAT является скалярной величиной, ее можно сохранить с элементе хэша или массива с информацией о целой группе людей и далее использовать приемы сортировки, объединения хэшей, выбора случайных записей и т,д" рассмотренные в главах 4 и Атрибуты записи, в том числе и "человека" из нашего примера, всегда являются скалярами. Конечно, вместо строк можно использовать числа, но это банально. Настоящие возможности открываются в том случае, если атрибуты записи также представляют собой ссылки. На этом этапе мы концептуально выходим за пределы простых записей и переходим к созданию сложных структур, которые представляют запутанные отношения между хранящимися в них данных. Хотя они могут использоваться для реализации традиционных структур данных

> Смотри также -------------------------------
perlref( 1); perllol( 1); perldsc( 1).


© copyright 2000 Soft group
Используются технологии uCoz