ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП |
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы. |
Ссылки и записиВведениеВ Perl существуют три основных типа данных: скалярные величины, массивы и хэши. Конечно, многие программы удается написать и без сложных структур данных, но обычно простых переменных и списков все же оказывается недостаточно. Три встроенные структуры данных Perl в сочетании со ссылками позволяю! строить сколь угодно сложные и функциональные структуры данных - те самыг записи, которых так отчаянно не хватало в ранних версиях Perl. Правильно выбирая структуру данных и алгоритм, вы иногда выбираете между элегантпои программой, которая быстро справляется со своей задачей, и убогой поделкой, ра ботающей с черепашьей скоростью и нещадно пожирающей системные ресурсы. Первая часть этой главы посвящена созданию и использованию простых ссылок. Во второй части рассказывается о применении ссылок для создания структур данных более высокого порядка.СсылкиЧтобы хорошо понять концепцию ссылок, сначала необходимо разобраться с тем. как в Perl хранятся значения переменных. С любой определенной переменной ассоциируется имя и адрес области памяти. Идея хранения адресов играет для ссылок особую роль, поскольку в ссылке хранятся данные о местонахождении другой величины. Скалярная величина, содержащая адрес области памяти, называется ссылкой. Значение, хранящееся в памяти по данному адресу, называется субъектом (referent) (рис. 11.1). Субъект может относиться к одному из встроенных типов данных (скалярная величина, массив, хэш, ссылка, код или глоб) или представлять собой пользовательский тип, основанный на одном из встроенных типов.Reference  Ox83c6c Referent
Рис.11.1. Ссылка и субъект
Субъекты в Perl типизованы. Это означает, что ссылку на массив нельзя
интерпретировать как ссылку на хэш. При подобных попытках инициируется
исключение. В Perl не предусмотрен механизм преобразования типов, и это
было сделано намеренно. На первый взгляд кажется, что ссылка - обычный
адрес с сильной типизацией. На самом деле это нечто большее. Perl берет
на себя автоматическое выделение и освобождение памяти (сборку мусора)
для ссылок так же, как и для всего остального. С каждым блоком памяти в
Perl связан счетчик ссылок, который определяет количество ссылок па данный
субъект. Память, используемая субъектом, возвращается в пул свободной памяти
процесса лишь при обнулении счетчика ссылок. Тем самым гарантируется, что
вы никогда не получите недопустимую ссылку - забудьте об аварийных завершениях
и ошибках защиты, часто возникающих при неправильной работе с указателями
в С. Освобожденная память передается Perl для последующего использования,
но лишь немногие операционные системы возвращают ее себе. Это связано с
тем, что в большинстве схем распределения памяти используется стек, а при
освобождении памяти в середине стека операционная система не сможет вернуть
ее без перемещения всех остальных блоков. Перемещение нарушит целостность
указателей и прикончит вашу программу. Чтобы перейти от ссылки к субъекту,
снабдите ссылку символом типа для тех данных, к которым вы обращаетесь.
Например, если $sref является ссылкой на скалярную величину, возможна следующая
запись:
Для обращения к отдельному элементу массива или хэша, на который у вас
имеется ссылка, используется ассоциативный оператор, оператор -> ("стрелка")
- например, $rv->[37] или $rv->{"wilma"}. Помимо разыменования ссылок на
массивы и хэши, стрелка также применяется при косвенном вызове функций
через ссылки - например, $code_ref->("arg1", "arg2") (см. рецепт 11.4).
Если вы работаете с объектами, то с помощью стрелки можно вызывать их методы,
$object->methodname("arg1", "arg2"), как показано в главе 13 "Классы, объекты
и связи". Правила синтаксиса Perl делают разыменование сложных выражений
нетриви-1ьной задачей. Чередование правых и левых ассоциативных операторов
не рекомендуется. Например, $$х[4] - то же самое, что и $х->[4]; иначе
говоря, $х интерпретируется как ссылка на массив, после чего из массива
извлекается четвертый элемент. То же самое записывается в виде ${$х}[4].
Если вы имели в виду "взять четвертый элемент @х и разыменовать его в скалярное
выражение", воспользуйтесь ${$х[4]}. Старайтесь избегать смежных символов
типов ($@%&) вез-.'-. кроме простых и однозначных ситуаций типа %hash
= %$hashref. Приведенный выше пример с $$sref можно переписать в виде:
Создавать ссылки можно даже для констант; при попытке изменить значенш
субъекта происходит ошибка времени выполнения:
Анонимные данныеСсылки на существующие данные часто применяются для передачи аргументов функции, но в динамическом программировании они бывают неудобны. Иногда ситуация требует создания нового массива, хэша, скалярной величины или функции, но вам не хочется возиться с именами. Анонимные массивы и хэши в 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: :Handle->new().
Рис. 11.2. Именованные субъекты
Рис. 11.3. Анонимные субъекты ЗаписиСсылки традиционно применялись в Perl для обхода ограничения, согласно которому массивы и хэши могут содержать только скаляры. Ссылки являются скалярами, поэтому для создания массива массивов следует создать массив ссылок на массивы. Аналогично, хэши хэшей реализуются как хэши со ссылками на хэши: массивы хэшей - как массивы ссылок на хэши; хэши массивов - как хэши ссылок на массивы и т. д. Имея в своем распоряжении эти сложные структуры, можно воспользоваться ими для реализации записей. Запись представляет собой отдельную логическую единицу, состоящую из различных атрибутов. Например, запись, описывающая человека, может содержать имя, адрес и дату рождения. В С подобные вещи называются структурами (structs), а в Pascal - записями (RECORDs). В Perl для них не существует специального термина, поскольку эта концепция может быть реализована разными способами. Наиболее распространенный подход в Perl заключается в том, чтобы интерпретировать хэш как запись, где ключи хэша представляют собой имена полей записи, а ассоциированные величины - значения этих полей. Например, запись "человек" может выглядеть так:$Nat = { "Name" => "Leonhard Euler", "Address" => "1729 Ramanujan Lane\nMathworld, PI 31416", "Birthday" => Ox5bb5580, Поскольку ссылка $NAT является скалярной величиной, ее можно сохранить с элементе хэша или массива с информацией о целой группе людей и далее использовать приемы сортировки, объединения хэшей, выбора случайных записей и т,д" рассмотренные в главах 4 и 5. Атрибуты записи, в том числе и "человека" из нашего примера, всегда являются скалярами. Конечно, вместо строк можно использовать числа, но это банально. Настоящие возможности открываются в том случае, если атрибуты записи также представляют собой ссылки. Например, атрибут "Birthday" может храниться в виде анонимного массива, состоящего из трех элементов: день, месяц и год. Выражение $person->{"BIrthday"}->[0] выделяет из даты рождения поле "день". Дата также может быть представлена в виде хэша, для доступа к полям которого применяются выражения вида $person->{ "Birthday" }->{"day"}. После включения ссылок в коллекцию приемов перед вами откроются многие нетривиальные и полезные стратегии программирования. На этом этапе мы концептуально выходим за пределы простых записей и переходим к созданию сложных структур, которые представляют запутанные отношения между хранящимися в них данных. Хотя они могут использоваться для реализации традиционных структур данных (например, связанных списков), рецепты второй части этой главы не связаны ни с какими конкретными структурами. В них описываются обобщенные приемы загрузки, печати, копирования и сохранения обобщенных структур данных. Завершающая программа этой главы демонстрирует работу с бинарными деревьями. > Смотри также -------------------------------
|