На этом шаге мы рассмотрим вопросы создания и использования символических ссылок.
В предыдуших шагах мы говорили, что если ссылка не определена, но ее присутствие требуется контекстом, то она создается автоматически.
Если же определенная ранее скалярная величина не является ссылкой, но используется в качестве ссылки, то ее называют символической ссылкой. Значение символической ссылки интерпретируется как имя некоторой переменной. Над этой переменной будут выполняться все операции, применяемые к символической ссылке. Вспомним, что значением жесткой ссылки является адрес. В следующем примере переменная $name_a используется как символическая ссылка на переменную $а.
$name_a = "a"; $$name_a = 17; @$name_a = (1,2,3); $name_a->[3] = 4; %$name_a = ("one"=>l, "two"=>2, "three"=>3); &$name_a();
В строке 2 переменной $а присваивается значение 17. В строке 3 определяется и инициализируется массив @а с элементами (1,2,3). В строке 4 к массиву @а добавляется четвертый элемент со значением 4. В строке 5 инициализируется хеш-массив %а. В строке 6 осуществляется вызов функции а() (предположим, что такая функция существует).
Символическая ссылка может указывать только на переменную, имя которой содержится в таблице символов пакета.
Лексические переменные, определяемые при помощи функции my(), в таблицу символов не входят, поэтому их имена невидимы для механизма, реализующего символические ссылки.
Для иллюстрации рассмотрим следующий пример:
$name_a="a"; { my $a="Hello!"; print $$name_a; };
Здесь переменная $name_a используется в качестве символической ссылки на переменную $а, и можно предположить, что результатом выполнения этой последовательности будет вывод строки "Hello!". В действительности переменная $а является невидимой для символической ссылки, поскольку она определена как лексическая переменная внутри блока {...}. Поэтому в результате выполнения данного фрагмента будет напечатана пустая строка.
Применение символических ссылок является потенциально опасным из-за возможности возникновения смысловых ошибок. Например, может показаться, что в результате выполнения следующей последовательности операторов:
$а[0]="b"; # .................... $b[0]=2; $b[1]=2; # .................... $а[0][0]=0; # .................... $prod = $b[0]*b[l];
переменная $prod получит значение 4. Но это не так. В строке 6 мы осуществляем присваивание, рассчитывая на то, что будет применен известный механизм неявного создания жесткой ссылки $а[0]. Мы "забыли" о том, что значение $а[0] уже использовалось в строке 1 и, следовательно, в строке 6 элемент массива $а[0] является символической ссылкой, указывающей на переменную с именем "b". Это имя будет подставлено вместо символической ссылки, в результате чего элемент массива b[0] получит новое значение 0. В итоге значение переменной $prod будет равно 0.
Во избежание подобных ошибок можно запретить использование символических ссылок в пределах текущего блока при помощи директивы:
use strict 'refs';
Это ограничение, если требуется, можно отменить для внутреннего блока при помощи другой директивы:
no strict 'refs';
use strict 'refs'; $ {name} ; ${"name"} ;
вторая строка представляет собой просто значение переменной $name, а третья строка интерпретируется как символическая ссылка, указывающая на переменную $name и вследствие применения директивы use strict 'refs' вызывает сообщение об ошибке вида:
Can't use string ("name") as a SCALAR ref while "strict refs" in use
Со следующего шага мы начнем рассматривать примеры использования ссылок.