Ваш map
возвращает последовательность значений List
, каждое из которых содержит два Pair
values.
Передача этого в хэш не приведет к его автоматическому сглаживанию, и каждый List
становится ключом или значением хеша.
Есть несколько способов заставить его делать то, что вы хотите:
Использование flat
Вы можете использовать встроенную функцию flat
, чтобы сгладить результат map
, чтобы хэш получил последовательность Pair
:
<H He>
==> map {
(state $n)++;
+$n => ~$_,
~$_ => +$n
}\
==> flat()
==> my %elements;
%elements.say; # {1 => H, 2 => He, H => 1, He => 2}
%elements{2}.WHAT.say; # (Str)
И map
, и flat
возвращают ленивые последовательности, так что это (теоретически) эффективно использует память, даже если список элементов велик.
- Примечание: я также написал
+$n
вместо $n
, потому что оператор построения =>
Pair (как и оператор построения ,
List) не "деконтейнеризирует" свои аргументы - если вы дадите ему такой контейнер элемента как переменная $
, она будет привязана к ней напрямую, а не к содержащемуся в ней значению, что приводит к тому, что следующее $n++
также влияет на Pair
, возвращенное из предыдущей итерации. Предоставление оператору построения пары выражения значения вместо переменной позволяет избежать этого.
Использование slip
slip
— это внутренняя версия flat
:
<H He>
==> map {
(state $n)++;
slip
+$n => ~$_,
~$_ => +$n
}\
==> my %elements;
Каждая итерация map
теперь возвращает значение типа Slip
, которое точно такое же, как List
, за исключением того, что оно автоматически растворяется в любом родительском элементе. список, частью которого он становится.
Рефакторинг
Если вы не привязаны к своему конкретному подходу, вот два потенциально более понятных способа создания одного и того же хэша:
my @keys = 1..*;
my @values = <H He>;
my %elements = flat (@keys Z=> @values), (@values Z=> @keys);
Or:
my %elements = 1..* Z=> <H He>;
push %elements, %elements.invert;
(Z
— метаоператор "zip")
person
smls
schedule
04.09.2016
map( { ++$ => ~$_ } )
или<H He> Z=> 1..*
для создания начального набора пар. - person Brad Gilbert   schedule 08.09.2016