Вам не хватает некоторых важных аспектов работы со ссылками.
Начиная с основ, идентификатором в Perl является строка, соответствующая [a-zA-Z_]\w+
, исключая сложности юникода.Этот идентификатор может быть пустым или иметь префикс с символом.
Наиболее важным и часто пропускаемым символом является глоб, *
, который является контейнером всех переменных (по крайней мере, до тех пор, пока my
не должен былиспортить вечеринку и быть другим, прячась в блокноте).
Если у вас есть идентификатор с именем foo
, то шар *foo
содержит все, что foo
может быть:
$foo as a scalar, a singular value
@foo as an array, a plural value
%foo as a hash, a plural value
&foo as code, singular if a reference \&foo, could be plural if making a call
Существуют и другие типы, но они встречаются реже.
В каждом из приведенных выше примеров сигил помещается перед идентификатором и разыменовывает ссылочные значения, хранящиеся в глобе *foo
.Полный синтаксис этого немного громоздкий @{*foo{ARRAY}}
, поэтому perl позволяет вам опустить печально пропущенный символ glob и использовать другие напрямую.Вы можете оставить скобки, ${foo}
или @{foo}
или любой другой символ, что означает то же самое, что и $foo
и @foo
соответственно.
Оказывается, вам не нужно помещать идентификатор пустого слова за символом или внутри скобок, но нужно использовать любое исключительное значение.
my $scalar_foo_ref = \$foo;
say $$scalar_foo_ref; # prints $foo
say ${$scalar_foo_ref}; # same
Символ всегда ожидает разыменования aзначение его типа (или того, которое может притвориться), и в противном случае будет выдано сообщение об ошибке.
Итак, предположим следующий код:
my @array = qw(a b c);
say $array[0]; # a
say join ', ' => @array; # a, b, c
Вы можете легко преобразовать его в использование ссылок.,Сначала вы измените объявление, чтобы использовать ссылки, которые являются скалярами и хранятся в $foo
:
my $array = [qw(a b c)]; # square brackets make an array ref
# or
my $array = \@array_of_hopefully_another_name; # \ does too
А затем в остальной части кода подставьте строку array
с именемссылка, $array
:
say $$array[0]; # a
say join ', ' => @$array; # a, b, c
Все, ссылки есть.Итак, наконец, к вашему коду.Возьмите следующие строки:
my $default = { name => 'James', madeby => 'name' };
$options = ($options,$defaults); #merge default and options hash
Во первых, вы правильно используете конструкцию {...}
для создания анонимной ссылки на хеш.Вы могли бы также написать это в ужасно многословной форме как:
my $default = do {my %hash = (name => 'James', madeby => 'name'); \%hash};
Но не делайте этого.
Следующая строка - это то, где возникают проблемы, и где вам нужно следоватьправила подстановки сверху.Вы, наверное, видели код, который выглядит следующим образом:
%options = (%options, %defaults);
И когда вы сменили сигил, все пошло не так.Что на самом деле делает perl, когда видит:
$options = ($options, $defaults);
Выполняется ли он, а затем выбрасывает все, кроме последнего элемента списка (в данном случае ($options,
, а затем назначает последний элемент скаляру наlhs из =
, что делает вашу строку эквивалентной:
$options = $defaults;
Что, конечно, не то, что вы хотели. Вместо этого замените свои имена хеш-ссылок на имена без слов:
%$options = (%$options, %$defaults);
Возможно, это слияние в неправильном порядке, при этом ваши значения по умолчанию переопределяют параметры. Чтобы исправить это, просто поменяйте местами:
%$options = (%$defaults, %$options);
Примените эти изменения в коде, где вы используете ссылки.Вещи должны снова обрести смысл.