Шаг 116.
Способы передачи по ссылке параметров-массивов. Использование типа typeglob

    На этом шаге мы рассмотрим использование типа typeglob.

    Первый подход, более старый, заключается в использовании внутреннего типа данных, называемого typeglob. Принадлежность к типу typeglob обозначается префиксом "*". Префикс "*" можно рассматривать как метасимвол, вместо которого может стоять любой из префиксов "$", "§", "%", "&", обозначающих тип данных "скаляр", "массив", "хеш-массив", "функция" соответственно. Интерпретатор преобразует переменную типа typeglob, например, *abc, в скалярную величину. Эта величина является ссылкой на гнездо в таблице символов, содержащее элементы разных типов с одинаковым именем abc, и представляет любой из этих элементов. Например, запись *abc обозначает всю совокупность, а также любую из следующих переменных: скаляр $abc, массив @abc, хеш %abc, функция &abc.

    Передача в подпрограмму вместо параметра-массива или хеш-массива соответствующей переменной типа typeglob является имитацией передачи параметра-массива (хеш-массива) по ссылке с сохранением его целостности. Рассмотрим следующий пример.

#! perl -w
sub doublargs 
{
  local (*mylist, *myhash) = @_; 
  foreach $item (@mylist) 
  {
     $item *= 2; 
  } 
  foreach $key (keys %myhash) 
  {
    $myhash{$key} *= 2;
  }
}

@somelist=(1,2,3) ;
%somehash=("one"=>5, "two"=>15, "three"=>20); 
print "начальные значения: \n\@somelist=@somelist\n"; 
foreach $key (keys %somehash) 
{
  print "\$somehash{$key}=$somehash{$key}"; 
}
print "\n";

doublargs (*somelist, *somehash);
print "итоговые значения: \n\@somelist=@somelist\n"; 
foreach $key (keys %somehash) 
{
  print "\$somehash{$key}=$somehash{$key}"; 
} 
print "\n";
Текст этого примера можно взять здесь.

    Подпрограмма doublargs принимает на вход массив и хеш-массив и изменяет их элементы, умножая на 2. Вместо массива и хеш-массива в подпрограмму передаются соответствующие переменные типа typeglob, которые легко выделить из массива @_, так как фактически они являются скалярами. Обратите внимание на применение функции local(). Использовать вместо нее функцию my() здесь нельзя. Переменная типа typeglob не может быть локальной, она представляет несколько одноименных переменных разных типов из таблицы символов. Далее возникает вопрос, каким образом изменение в подпрограмме массива @mylist влияет на изменение фактического параметра @somelist. Дело в том, что операция присваивания вида *х = *у создает синоним для гнезда таблицы символов , так что осуществление операции над $х, @х, %х эквивалентно осуществлению этой операции над $y, @y, %y. В результате присваивания

  local(*mylist,   *myhash)   = @_;
создается псевдоним *mylist для *somelist, поэтому все изменения элементов массива @mylist внутри подпрограммы эквивалентны изменениям элементов массива @somelist. Все сказанное справедливо и для хеш-массивов %myhash и %somehash. Результат подтверждает корректность передачи массива и хеш-массива по ссылке:


Рис.1. Результат работы примера

    На следующем шаге мы рассмотрим использование ссылок.




Предыдущий шаг Содержание Следующий шаг