Поиск

Основные сведения

Обычные скалярные переменные создаются с помощью оператора присваивания, например:

После выполнения этого оператора Perl создаст скалярную переменную $а и присвоит ей строковое значение "Скаляр". Итак, до сих пор вы не встретили ничего необычного, не правда ли? Можете считать, что в компьютере выделяется участок памяти, называемый $а, который содержит строковое значение, как показано ниже.

Теперь, если вы присвоите значение скаляра $а другому скаляру, например $Ь с помощью оператора $Ь=$а, в памяти компьютера создается две одинаковые копии данных, которым присваиваются разные имена, как показано ниже.

Подобный оператор присваивания может пригодиться в том случае, если вы действительно хотите иметь две независимые копии данных. Однако чаще всего нужно, чтобы обе переменные $а и $Ь соответствовали одному и тому же участку данных, а не его копии. В этом случае следует создать ссылку. Ссылка является просто указателем на некоторый участок памяти. Не забывайте, что она не содержит никаких реальных данных! Ссылка обычно хранится в скалярной переменной.

Чтобы создать ссылку на скалярную переменную, перед именем переменной следует поместить символ обратной косой черты. Например, чтобы создать ссылку $ref на переменную $а, используется такой оператор присваивания:

В результате в памяти компьютера создается такая структура:

При этом в переменной $ref не содержится никаких реальных данных; в эту переменную помешается указатель (или адрес) переменной $а. Обратите внимание, что при создании ссылки значение переменной $а не изменяется. После создания ссылки с переменной $а можно выполнять те же действия, что и с обычной переменной, например присваивать значения ($а="строка") или распечатывать (print $а).

Поскольку в переменной $ref содержится ссылка на переменную $а, а не на сами данные, с ней нельзя выполнять те же действия, что и с обычными переменными. Например, если вы попытаетесь распечатать значение переменной $ref с помощью оператора print, то получите нечто вроде SCALAR (0x0000). Чтобы получить доступ к содержимому переменой $а через ссылку $ref, необходимо выполнить так называемую операцию разыменования переменной $ref. Представьте себе, что на предыдущем рисунке вы должны двигаться по стрелке к переменной $а. Это и будет разыменование. Например, чтобы распечатать значение переменной $а через ссылку $ref, к ссылке необходимо добавить дополнительный символ $:

В этом примере, естественно, подразумевается, что переменная $ref является ссылкой, а дополнительный знак доллара говорит интерпретатору о том, что это ссылка на переменную скалярного типа. В результате выбирается и распечатывается значение переменной, на которое указывает переменная $ref.

С помощью ссылки можно также изменить первоначальное значение переменной. Это еще одно преимущество использования ссылок по сравнению с переменными-копиями. В следующем примере значение переменной $а будет изменено:

Данный оператор будет выполняться по следующей схеме:

Если по ошибке в операторе присваивания вы укажете $ref вместо $$ref:

ссылка на переменную $а аннулируется и переменной $ref присваивается реальное значение — строка "Ошибка!", как показано ниже.

После выполнения этого оператора переменная $ref становится обычным скаляром, содержащим текстовое значение. Ссылку можно присвоить другой переменной с помощью оператора присваивания так же, как это происходит со скалярами, например:

В результате получается следующая схема:

В этом примере для получения значения переменной $name ("Евгений") можно использовать две ссылки $$nref и $$oref. Кроме того, можно создать ссылку на ссылку, как показано ниже на примере:

В данном случае цепочка ссылок будет выглядеть так:

Теперь, для того чтобы добраться до значения переменной $bоок через ссылку $bref2, нужно использовать конструкцию $$$bref2. Обратите внимание, что для ссылки на переменную $book через $bref использовалась конструкция $$bref. Таким образом, "лишний" знак доллара обозначает, что для доступа к оригинальному значению переменной $book нужно сделать дополнительную операцию разыменования.

Ссылки на массивы

Ссылки могут быть также созданы на массивы и хэши. Причем делается это так же, как и ссылка на обычную переменную, — перед именем массива или хэша в операторе присваивания нужно поставить обратную косую черту, например:

В результате скалярная переменная $aref будет содержать ссылку на массив @аrr. Визуально это можно представить в виде следующей диаграммы:

Для доступа к элементам массива @аrr через переменную-ссылку $aref можно использовать один из приведенных ниже операторов:

Для улучшения читабельности программы можно поместить переменную, ссылающуюся на массив, в фигурные скобки, как показано ниже на примерах.

Например, в следующем фрагменте кода распечатываются все элементы массива @аrr с помощью переменной-ссылки $aref.

Ссылки на хэши

Ссылка на хэш создается точно так же, как и на обычный скаляр или массив: нужно поместить перед именем хэша обратную косую черту:

В результате скалярная переменная $href будет содержать ссылку на хэш @hash. Визуально это можно представить в виде следующей диаграммы:

Для доступа к элементам хэша %hash через переменную-ссылку $href можно использовать один из приведенных ниже операторов.

Например, для распечатки всех элементов хэша %hash с помощью переменной-ссылки @href можно воспользоваться следующим фрагментом кода:

Ссылки на аргументы

После того как мы рассмотрели ссылки на массивы и хэши, пришло время поговорить о том, как можно передать в подпрограмму несколько массивов или хэшей.

Из материала 8-го занятия, "Функции", вы уже знаете, что приведенный ниже фрагмент кода не работает.

Этот фрагмент кода не работает потому, что в операторе вызова подпрограммы getarrays(@fruit, @veggies) второй массив @veggies затеняется первым массивом @fruit, и элементы обоих массивов присваиваются одному массиву @_. Внутри подпрограммы getarrays выполняется оператор присваивания (@a, @Ь)=@_ . В результате все элементы массива @veggies окажутся в массиве @а, а массив @b окажется пустым.

Поскольку элементы обоих массивов при передаче в подпрофамму getarrays оказались в массиве @_, нельзя определить, где заканчивается один массив и начинается другой. В результате получился один большой массив.

Чтобы разрешить проблему, необходимо воспользоваться ссылками, т.е. в подпрофамму getarrays нужно передавать не два массива, а только ссылки на них. Вот пример:

Теперь подпрограмме getarrays всегда передаются два параметра, являющиеся ссылками на массивы. При этом размерность этих массивов не имеет никакого значения. Для доступа к элементам массивов внутри подпрограммы getarrays используются переменные-ссылки $fruit_ref, $veg ref, как показано ниже.

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

В примере слева хэш передается обычным образом. При этом массиву @_ присваиваются пары ключ-значение передаваемого в подпрограмму хэша %hash. Внутри подпрограммы changehash элементы массива @_ копируются в новый хэш %local_hash, который модифицируется, после чего подпрограмма завершает свое выполнение. В результате хэш %local_hash уничтожается, а первоначальный хэш %hash в главной программе остается без изменений.

В примере справа в подпрофамму changehash через массив @_ передается ссылка на хэш fchash. В начале подпрофаммы ссылка копируется в локальную переменную $href, но, несмотря на это, она по-прежнему указывает на хэш %hash. Далее внутри подпрофаммы происходит изменение хэша, на который указывает ссылка $href, и подпрофамма завершает свое выполнение. В результате в хэше %hash появится новый ключ beast, которому присвоено значение 'медведь'.

При передаче аргументов в подпрофаммы массив §_ на самом деле является массивом ссыпок. Таким образом, при изменении элементов массива @_ будут изменяться и значения аргументов, передаваемых в подпрофамму. Однако учтите, что изменение аргументов, переданных в подпрофамму, считается плохим стилем программирования. Поэтому, если нужно модифицировать в подлрофам-ме передаваемые ей значения, используйте ссылки. В результате при анализе программы сразу становится понятно, что она модифицирует свои аргументы.
Создание структур

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

В приведенном ниже примере хэш %hash создается внутри блока кода, причем он является локальным для этого блока.

Внутри блока скаляру $href присваивается ссылка на локальный хэш %hash. После завершения работы блока ссылка на хэш %hash остается в активном состоянии, несмотря на то что переменная %hash была объявлена локальной для блока, вышла из зоны видимости и должна быть аннулирована. Таким образом, ссылки на скаляры, массивы, хэши и структуры будут существовать даже после выхода этих объектов. из зоны видимости блока или подпрограммы. В нашем примере с помощью ссылки $href можно модифицировать хэш %hash вне зоны его видимости (т.е. за пределами блока, в котором он был объявлен).

Если вы внимательно посмотрите на предыдущий блок кода, то увидите, что нет особого смысла объявлять локальный хэш и назначать ему имя %hash, поскольку оно используется только один раз. Для подобных случаев в Perl предусмотрено специальное средство создания ссылок на структуры данных без назначения им промежуточных имен (типа %hash). Речь идет о так называемой анонимной памяти (anonymous storage), В приведенном ниже примере создается ссылка на анонимный хэш, которая помещается в переменную $ahref.

Элементы анонимного хэша помещаются в фигурные скобки. Такая конструкция возвращает ссылку на созданный хэш, которую нужно присвоить переменной-ссылке. Для работы с анонимным хэшем используется методика, описанная выше в разделе "Ссылки на хэши".

Анонимный массив создается с помощью квадратных скобок [], как показано ниже на примере.

Для работы с анонимным массивом используется методика, описанная выше в разделе "Ссылки на массивы".

Данные, на которые указывают переменные-ссылки, уничтожаются, как только соответствующая переменная-ссылка выходит из области видимости, как показано ниже на примере.

Следует отметить, что если в программе используется оператор use strict, то этот пример будет скомпилирован с ошибками. Причина заключается в том, что Perl считает переменную $ref глобальной, поскольку она используется в последнем операторе, и в то же самое время она объявлена локальной переменной блока, что недопустимо. Если же активизировать режим выдачи предупреждений с помощью ключа -w, то, вероятнее всего, Perl выведет сообщение undefined value (неопределенное' значение), даже если при этом не используется оператор use strict.

Описанные выше анонимные хэши и массивы можно объединять в структуры данных, которые будут описаны в следующем разделе. Поскольку для хранения ссылок на хэши и массивы используются одиночные скалярные переменные, их без проблем можно поместить в элемент массива или хэша, как показано ниже на примере.