Ответ 1
Простой хэш близок к массиву. Их инициализации даже выглядят похожими. Сначала массив:
@last_name = (
"Ward", "Cleaver",
"Fred", "Flintstone",
"Archie", "Bunker"
);
Теперь представим одну и ту же информацию с хешем (aka ассоциативный массив):
%last_name = (
"Ward", "Cleaver",
"Fred", "Flintstone",
"Archie", "Bunker"
);
Хотя они имеют одинаковое имя, массив @last_name
и хэш %last_name
полностью независимы.
С массивом, если мы хотим узнать фамилию Арчи, нам нужно выполнить линейный поиск:
my $lname;
for (my $i = 0; $i < @last_name; $i += 2) {
$lname = $last_name[$i+1] if $last_name[$i] eq "Archie";
}
print "Archie $lname\n";
С хешем он гораздо более прямой синтаксически:
print "Archie $last_name{Archie}\n";
Предположим, что мы хотим представлять информацию только с немного более богатой структурой:
- Кливер (фамилия)
- Уорд (имя)
- Июнь (имя супруга)
- щебенки
- Фред
- Вильма
- Бункер
- Archie
- Edith
До того, как появились ссылки, плоские хэши-значения ключа были о лучшем, что мы могли бы сделать, но ссылки позволяют
my %personal_info = (
"Cleaver", {
"FIRST", "Ward",
"SPOUSE", "June",
},
"Flintstone", {
"FIRST", "Fred",
"SPOUSE", "Wilma",
},
"Bunker", {
"FIRST", "Archie",
"SPOUSE", "Edith",
},
);
Внутренне ключи и значения %personal_info
являются всеми скалярами, но значения являются специальным видом скалярных ссылок: хеш-ссылок, созданных с помощью {}
. Ссылки позволяют нам моделировать "многомерные" хеши. Например, мы можем добраться до Вильмы через
$personal_info{Flintstone}->{SPOUSE}
Обратите внимание, что Perl позволяет нам опустить стрелки между индексами, поэтому приведенное выше эквивалентно
$personal_info{Flintstone}{SPOUSE}
Это много набрав, если вы хотите узнать больше о Fred, поэтому вы можете получить ссылку как своего рода курсор:
$fred = $personal_info{Flintstone};
print "Fred wife is $fred->{SPOUSE}\n";
Потому что $fred
в фрагменте выше - hashref, стрелка необходима. Если вы оставите это, но с умным включением use strict
, чтобы помочь вам поймать подобные ошибки, компилятор будет жаловаться:
Global symbol "%fred" requires explicit package name at ...
Ссылки на Perl аналогичны указателям на C и С++, но они никогда не могут быть нулевыми. Указатели на C и С++ требуют разыменования, а также ссылки на Perl.
Параметры функции C и С++ имеют семантику pass-by-value: они просто копии, поэтому модификации не возвращаются к вызывающему. Если вы хотите увидеть изменения, вам нужно передать указатель. Вы можете получить этот эффект со ссылками на Perl:
sub add_barney {
my($personal_info) = @_;
$personal_info->{Rubble} = {
FIRST => "Barney",
SPOUSE => "Betty",
};
}
add_barney \%personal_info;
Без обратной косой черты add_barney
получило бы копию, которая была выброшена, как только возвращается sub.
Обратите внимание также на использование "жирной запятой" (=>
) выше. Он автоматически выводит строку слева и делает инициализацию хеширования менее синтаксически шумной.