Массивы и sigil @
Разбираемся, как Perl хранит списки значений, почему один и тот же массив в разных местах кода называют то @arr, то $arr[0], и что такое срез массива.
Массив — переменная Perl, которая хранит упорядоченный список значений. Sigil массива — знак
@, а обращение к отдельному элементу внутри него — снова через$.
От одного значения к списку
В прошлом уроке мы разобрали скаляры — переменные для одного значения. Но что, если нужно хранить не одно имя ученика, а список из тридцати имён целого класса? Заводить тридцать отдельных переменных $uchenik1, $uchenik2 и так далее было бы неудобно и бессмысленно. Для таких случаев в Perl есть массив — переменная, которая хранит сразу много значений по порядку, пронумерованных с нуля, как в большинстве языков программирования.
Sigil массива — знак @ (собака, at). Если вы работали с массивами в JavaScript или списками в Python, идея знакома — разница только в синтаксисе.
Объявление массива
my @uchenniki = ("Anya", "Boris", "Vera");
print "Klass: @uchenniki\n";
print "Vsego uchenikov: " . scalar(@uchenniki) . "\n";Вывод:
Klass: Anya Boris Vera
Vsego uchenikov: 3Разбираем построчно
Строка my @uchenniki = ("Anya", "Boris", "Vera"); объявляет массив uchenniki и заполняет его тремя строками, перечисленными в круглых скобках через запятую — такая запись в скобках называется списком (list). Обратите внимание: при объявлении используется sigil @, потому что мы работаем с переменной как с целым списком.
Дальше — интересная деталь: строка print "Klass: @uchenniki\n"; использует интерполяцию массива прямо внутри двойных кавычек, точно как со скалярами в прошлом уроке. Perl автоматически превращает массив в строку, вставляя пробел между элементами — поэтому вывод показывает все три имени через пробел.
Функция scalar(@uchenniki) заслуживает отдельного внимания: она заставляет Perl посмотреть на массив «в скалярном контексте» — и в этом контексте массив превращается не в список элементов, а в одно число: количество элементов в нём. Это первое знакомство с идеей контекста, которую подробно разберём в последнем уроке раздела — а пока достаточно запомнить, что scalar(@massiv) — стандартный способ узнать длину массива.
Обращение к элементу: sigil меняется на $
Вот что особенно сбивает с толку новичков: чтобы обратиться к одному конкретному элементу массива, sigil @ меняется на $.
my @frukty = ("Yabloko", "Grusha", "Banan");
print "Pervyy: $frukty[0]\n";
print "Posledniy: $frukty[-1]\n";Вывод:
Pervyy: Yabloko
Posledniy: BananЛогика такая: сам массив целиком @frukty — это список, много значений сразу, поэтому у него sigil @. А вот $frukty[0] — это уже одно конкретное значение (первый элемент, индексация начинается с нуля, как в Python или JavaScript), поэтому используется $, sigil скаляра. Это не опечатка и не исключение из правил — это последовательная логика Perl: sigil показывает не «какая это переменная», а «сколько значений вы сейчас имеете в виду» — одно или много. Индекс -1 — ещё одна удобная возможность Perl: отрицательные индексы считают элементы с конца, -1 — последний элемент, без нужды заранее знать длину массива.
Обход массива циклом foreach
Чтобы пройтись по всем элементам массива по очереди, используют цикл foreach — почти как for...of в JavaScript или простой for item in list в Python.
my @predmety = ("Matematika", "Fizika", "Informatika");
foreach my $predmet (@predmety) {
print "Predmet: $predmet\n";
}Вывод:
Predmet: Matematika
Predmet: Fizika
Predmet: InformatikaНа каждом шаге цикла переменная $predmet (обратите внимание — скаляр, потому что на каждом конкретном шаге мы держим в руках ровно одно значение) по очереди получает каждый элемент массива @predmety. Тело цикла в фигурных скобках выполняется столько раз, сколько элементов в массиве.
Срезы массива
Срез (slice) — это способ достать сразу несколько элементов массива одной командой, а не по одному. Синтаксис снова использует sigil @, потому что результат — список, а не одно значение.
my @chisla = (10, 20, 30, 40, 50);
my @srez = @chisla[1, 2, 3];
print "Srez: @srez\n";Вывод:
Srez: 20 30 40Запись @chisla[1, 2, 3] достаёт сразу три элемента с индексами 1, 2 и 3 (то есть второй, третий и четвёртый по счёту, поскольку нумерация с нуля) и складывает их в новый массив @srez. Обратите внимание на sigil: квадратные скобки те же, что и при обращении к одному элементу, но sigil перед именем — @, а не $, потому что результат — список из нескольких значений, а не одно число.
Частые ошибки новичков
Самая частая ошибка — использовать sigil @ там, где нужен $, или наоборот. Например, написать @frukty[0] вместо $frukty[0] для одного элемента — Perl не выдаст явную ошибку сразу, но результат окажется не тем, что ожидалось, потому что @frukty[0] технически воспринимается как срез из одного элемента, а не как обычное скалярное значение.
Вторая ошибка — забыть, что индексация начинается с нуля. Первый элемент массива — это $arr[0], а не $arr[1], как иногда интуитивно кажется новичкам, привыкшим считать «первый, второй, третий» с единицы.
Третья ошибка — пытаться напечатать массив без интерполяции, например через одинарные кавычки: print '@frukty'; выведет буквально текст @frukty, а не значения элементов, потому что, как мы помним из прошлого урока, в одинарных кавычках интерполяция не работает.
Итоги
- Массив хранит упорядоченный список значений, sigil массива —
@. - Обращение к отдельному элементу массива идёт через
$и индекс в квадратных скобках:$arr[0]— первый элемент,$arr[-1]— последний. scalar(@arr)возвращает количество элементов массива.- Срез — способ достать сразу несколько элементов через
@arr[индексы], результат — тоже массив, поэтому sigil снова@. - Цикл
foreach my $item (@arr) {...}— стандартный способ обойти все элементы массива по очереди.