В Perl результат присваивания (и, соответственно, работы с массивами и хэшами) зависит от контекста.
my @arr = (10, 20, 30); my $count = @arr; # $count == 3 my ($first, $second) = @arr; # $first == 10, $second == 20
Для хэшей:
my %h = (a=>1, b=>2, c=>3); my $size = %h; # $size == 3 в современных версиях Perl, но раньше это было не так!
Остерегайтесь присваивания целиком ссылки на массив вместо копирования содержимого!
Чем отличается присваивание массива ссылке и копирование содержимого массива?
Ответ:
my @a = (1,2,3); my $ref = \@a; # $ref — ссылка на массив, изменения через $ref видны в @a my @b = @a; # @b — новый массив, изменения @b никак не влияют на @a # Сравните: push @$ref, 4; # @a теперь (1,2,3,4) push @b, 5; # @a остается (1,2,3,4); @b — (1,2,3,5)
История 1
В проекте передавали массив в подпрограмму через ссылку, не понимая, что это именно ссылка: функция меняла его в месте вызова. Прилетели баги — в вызывающем коде структура данных уже была "испортена". Ожидали копию, получили alias.
История 2
Инженер рассчитывал, что скалярное присваивание
%hвернет реальное количество пар. Оказалось — в старых версиях Perl это поведение было другое: возвращалось число слотов/бакетов, а не длина! В итоге иногда возвращалось не 3, а другое число, что поломало статистику.
История 3
В крупной ETL-системе массивы копировали через ссылки, а потом неожиданно перетирали друг другу данные, потому что все работали с одним и тем же массивом, а не с независимыми копиями. Диагностика ошибки заняла несколько дней.