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