Ссылки в Perl ведут себя немного иначе, чем многие программисты используют из других языков программирования.Например, рассмотрим этот код Perl:
my %person = ();
$person{"name"} = "John Doe";
$person{"age"} = 34;
, а затем вы получите ссылку на него:
my $personRef = \%person;
В большинстве языков программирования это утверждение читается как " Получите адрес памятирезервное хранилище, используемое %person
и записать его в $personRef
".В этих языках я могу затем изменить %person
сам (а не память, на которую он указывает), и это не окажет никакого влияния на $personRef
, все еще указывая на ту же память, что и раньше, которая все еще содержит те же значения, что и раньше.
Но в Perl это утверждение скорее читается как " Позвольте $personRef
всегда указывать на память, используемую в настоящее время %person
".Важное ключевое слово здесь всегда, так как это означает, что если вы вносите изменения в %person
, эти изменения также немедленно отражаются ссылкой.
Таким образом, когда вы делаете это в Perl:
my %person = ();
$person{"name"} = "John Doe";
$person{"age"} = 34;
my $personRef = \%person;
%person = (); # <-- Assigns new empty hash!
$person{"name"} = "Jane Doe";
$person{"age"} = 47;
print "$personRef->{'name'}\n";
На самом деле он напечатает «Jane Doe», поскольку независимо от того, что вы делаете с %person
, $personRef
всегда будет указывать на используемую память %person
, даже когда вы назначаете новый пустой хеш для %person
, ссылка теперь будет указывать на этот пустой хеш.
Можно сказать, что в Perl ссылки не являются ссылками на память, используемую значениями, а на переменные, которые ссылаются на эти значения.В любое время, когда вы используете ссылку для доступа к значению, для этого используется текущее значение ссылочной переменной, и это могло много раз меняться с момента создания ссылки.
Принятый ответ решает эту проблемукопируя хэши:
my @people = ();
my %person = ();
$person{"name"} = "John Doe";
$person{"age"} = 34;
push @people, { %person };
%person = ();
$person{"name"} = "Jane Doe";
$person{"age"} = 47;
push @people, { %person };
Но подождите, где здесь копируются хэши?Ну, это магия Perl.Чтобы создать новый хеш, вы можете использовать этот синтаксис:
my %hash = (
"name" => "John Doe",
"age" => 34
);
Но это всего лишь синтаксический сахар, поскольку на самом деле вы также можете использовать ,
вместо =>
:
my %hash = ("name", "John Doe", "age", 34);
При преобразовании хеша в список каждый первый элемент списка является ключом, а каждый второй элемент списка - его значением, поэтому при создании хеша из списка значения списка интерпретируются именно таким образом.Теперь, если вы хотите напрямую создать ссылку на хеш, вы можете написать:
my $hashRef = { "name", "John Doe", "age", 34 };
И это в основном то же самое, что и запись:
my $hashRef = { %myHash };
Это читается как " Создайте новый хеш ({}
), заполните его значениями от %myHash
и напишите ссылку на него $hashRef
".Это именно то, что происходит в этой строке:
push @people, { %person };
За исключением того, что ссылка на вновь созданный хэш непосредственно помещается в массив.