Ссылки: как сделать массив массивов
Представь, что тебе нужно хранить таблицу — например, оценки нескольких учеников по нескольким предметам. Обычный массив Perl хранит только плоский список значений: числа, строки. А если нужно хранить массив внутри массива? Вот тут и появляются ссылки.
Ссылка (reference) — это переменная, которая хранит не сами данные, а адрес, где эти данные лежат в памяти. Звучит абстрактно, но на практике это просто способ «упаковать» массив или хеш в единое значение, которое можно передать дальше, положить в другую структуру или вернуть из функции.
Зачем это нужно
В Perl обычный массив не может напрямую содержать другой массив. Если попытаться положить один массив в другой через присваивание элементу, Perl «расплющит» его — все элементы вложенного массива просто окажутся в общем списке вперемешку с остальными. Это называется списковым контекстом, и для таблиц он не годится.
Решение — не класть массив целиком, а положить ссылку на него. Ссылка — это одно скалярное значение (как число или строка), поэтому она отлично помещается в элемент другого массива. Так и получается массив массивов, хеш массивов и любая другая вложенная структура.
Оператор \ — создаём ссылку
Чтобы получить ссылку на переменную, перед ней ставится обратный слэш \. Это работает для массивов, хешей и скаляров одинаково:
my @numbers = (10, 20, 30);
my $ref_to_array = \@numbers;
print $ref_to_array;Вывод:
ARRAY(0x55d3f2a1b2c0)Видно, что переменная $ref_to_array хранит не список чисел, а нечто вроде «адреса» — тип ARRAY и шестнадцатеричный идентификатор ячейки памяти. Это и есть ссылка: компактное значение, которое указывает на настоящий массив @numbers, лежащий где-то ещё.
Обрати внимание на важную деталь: ссылка хранится в скалярной переменной (с сигилом $), даже если ссылается на массив (у которого свой сигил @). Это правило без исключений: ссылка — это всегда скаляр, независимо от того, на что она указывает.
Оператор -> — разыменование
Получить обратно доступ к данным по ссылке называется разыменованием (dereferencing). Самый читаемый способ — стрелка ->:
my @numbers = (10, 20, 30);
my $ref_to_array = \@numbers;
print $ref_to_array->[0];
print "\n";
print $ref_to_array->[2];Вывод:
10
30Синтаксис $ref_to_array->[0] означает «пойди по ссылке $ref_to_array и возьми элемент с индексом 0 из массива, на который она указывает». Квадратные скобки после стрелки — знак того, что мы обращаемся к массиву. Для хешей вместо скобок используются фигурные — об этом в следующем уроке.
Собираем массив массивов
Теперь главный трюк: элементами обычного массива могут быть ссылки на другие массивы. Так получается «массив массивов» — по сути, таблица.
my @row1 = (1, 2, 3);
my @row2 = (4, 5, 6);
my @row3 = (7, 8, 9);
my @matrix = (\@row1, \@row2, \@row3);
print $matrix[1]->[2];Вывод:
6Разберём построчно. Сначала создаём три обычных массива-строки. Потом собираем @matrix — это массив, но его элементы не числа, а ссылки на @row1, @row2, @row3. Обращение $matrix[1] берёт второй элемент @matrix (индексация с нуля) — это ссылка на @row2. А ->[2] уже разыменовывает её и берёт третий элемент этого массива, то есть 6.
На практике чаще пишут анонимные массивы прямо на месте, без промежуточных переменных вроде @row1. Для этого квадратные скобки используются как конструктор:
my @matrix = (
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
);
print $matrix[2]->[0];Вывод:
7Квадратные скобки [1, 2, 3] в этом контексте — не индексация, а создание анонимного массива и сразу же ссылки на него. Это самый распространённый способ описывать таблицы и вложенные списки в реальном коде — компактно и наглядно.
Стрелка необязательна между скобками
Perl разрешает опускать стрелку между соседними квадратными или фигурными скобками — код $matrix[2]->[0] и $matrix[2][0] работают одинаково:
my @matrix = ( [1, 2, 3], [4, 5, 6] );
print $matrix[1][2];Вывод:
6Первая стрелка (сразу после имени переменной) тоже часто опускается на практике, но между двумя разными «уровнями» вложенности — например, между ссылкой на массив внутри хеша и следующим уровнем — её лучше сохранять для читаемости, особенно пока структура ещё не привычна.
Частые ошибки
Первая ошибка — забыть про сигил $ при обращении к элементу. Даже если структура называется @matrix, конкретный элемент — это скаляр, поэтому обращение начинается с $matrix[...], а не @matrix[...] (последнее означает совсем другое — срез массива).
Вторая — попытка напечатать ссылку и удивление, что вместо чисел вывелось что-то вроде ARRAY(0x...). Это не ошибка программы, а напоминание: ссылку нужно сначала разыменовать через ->, чтобы добраться до реальных данных.
Третья — путаница между \@array (ссылка на существующий именованный массив) и [1, 2, 3] (создание нового анонимного массива с сразу готовой ссылкой на него). Оба варианта дают ссылку, но используются в разных ситуациях: первый — когда массив уже где-то объявлен, второй — когда структура собирается «на лету».
Итоги
Ссылка — это скалярное значение, которое указывает на массив, хеш или другую переменную. Она создаётся оператором \ перед именем переменной, а квадратные и фигурные скобки без \ создают анонимные структуры сразу со ссылкой на них. Разыменование делается стрелкой ->, которую можно опускать между соседними уровнями вложенности. Благодаря ссылкам массив может содержать другие массивы — так получаются таблицы и любые вложенные структуры, которые пригодятся в следующем уроке.