В Perl 6 можно ли использовать массив в качестве хэш-ключа? - PullRequest
0 голосов
/ 26 апреля 2018

В документации по хэшу раздел Object keys, по-видимому, подразумевает, что вы можете использовать любой тип в качестве ключа хеша, пока вы указываете, но у меня возникают проблемы при попытке использовать массив как ключ:

> my %h{Array};
{}
> %h{[1,2]} = [3,4];
Type check failed in binding to parameter 'key'; expected Array but got Int (1)
in block <unit> at <unknown file> line 1

Возможно ли это сделать?

Ответы [ 2 ]

0 голосов
/ 27 апреля 2018

Если вас по какой-то причине действительно интересует только использование хэша объекта, обратитесь к ответу Лиз здесь, и особенно к ответам и комментариям к аналогичному предыдущему вопросу .

(окончательный 1 ) фокус этот ответ - простой способ использовать Array как [1,'abc',[3/4,Mu,["more",5e6],9.9],"It's {<sunny rainy>.pick} today"] в качестве обычного хеш-ключа строки.

Основным принципом является использование .perl для аппроксимации неизменяемого массива «тип значения» до тех пор, пока не появится канонический неизменяемый тип Positional с более устойчивым тип значения .WHICH.

Простой способ использования массива в качестве хеш-ключа

my %hash;
%hash{ [1,2,3].perl } = 'foo';
say %hash{ [1,2,3].perl }; # displays 'foo'

.perl преобразует свой аргумент в строку кода Perl 6, который является литеральной версией этого аргумента.

say [1,2,3].perl;    # displays '[1, 2, 3]'

Обратите внимание, как были добавлены пробелы, но это не имеет значения.

Это не идеальное решение. Вы, очевидно, получите неверные результаты, если вы измените массив между ключевыми обращениями. Менее очевидно, вы получите неверные результаты, соответствующие любым ограничениям или ошибкам в .perl:

say [my %foo{Array},42].perl; # displays '[(my Any %{Array}), 42]'

1 Это, надеюсь, конец моего окончательного окончательного ответа на ваш вопрос. См. мою предыдущую 10-ю (!!) версию этого ответа для обсуждения альтернативы использования префикса ~ для достижения более ограниченного, но схожего эффекта и / или чтобы попытаться осмыслить мой обмен с Лиз в комментариях ниже.

0 голосов
/ 27 апреля 2018

[1,2] внутри %h{[1,2]} = [3,4] интерпретируется как срез. Поэтому он пытается присвоить %h{1} и %{2}. А так как ключ должен быть Array, это плохо проверяет тип. Вот что говорит вам сообщение об ошибке.

Если вы детализируете массив, он «работает»:

my %h{Array};
%h{ $[1,2] } = [3,4];
say %h.perl;  # (my Any %{Array} = ([1, 2]) => $[3, 4])

Однако это, вероятно, не дает того, что вы хотите, потому что:

say %h{ $[1,2] };  # (Any)

Это потому, что хеши объектов используют значение метода .WHICH в качестве ключа в базовом массиве.

say [1,2].WHICH; say [1,2].WHICH;
# Array|140324137953800
# Array|140324137962312

Обратите внимание, что значения .WHICH для этих, казалось бы, идентичных массивов различны. Это потому, что Array являются изменчивыми. Как и List с, так что на самом деле это не сработает.

Так чего же вы пытаетесь достичь? Если порядок значений в массиве не важен, вы можете использовать Set s в качестве ключей:

say [1,2].Set.WHICH; say [1,2].Set.WHICH
# Set|AEA2F4CA275C3FE01D5709F416F895F283302FA2
# Set|AEA2F4CA275C3FE01D5709F416F895F283302FA2

Обратите внимание, что эти два .WHICH одинаковы. Так что вы можете написать это как:

my %h{Set};
dd %h{ (1,2).Set } = (3,4); # $(3, 4)
dd %h; # (my Any %{Set} = ((2,1).Set) => $(3, 4))

Надеюсь, это прояснит ситуацию. Больше информации на: https://docs.perl6.org/routine/WHICH

...