Может ли Perl 6 использовать сигил % для чего-то другого, кроме хэша?
В документах Perl 6 по переменным отмечается, что Сигилла % может использоваться с типами, выполняющими ассоциативную роль . Он специально упоминает пару, хэш иКарта . Но как я могу получить пару в переменную с %?
Если я использую ограничение типа, я получаю любопытную ошибку:
> my Pair %pair = Pair.new( 'a', 'b' )
Type check failed in assignment to %pair; expected Pair but got Str ("b")
in block <unit> at <unknown file> line 1
Если я назначаю без ограничения типа, я получаю хэш:
my %pair = Pair.new: 'a', 'b'; # Hash, not Pair
Переплетные работы:
my %pair := Pair.new: 'a', 'b'; # Pair
Но если я использую ограничение типа, Я получаю еще одну любопытную ошибку:
> my Pair %p2 := Pair.new: 'a', 'b';
Type check failed in binding; expected Associative[Pair] but got Pair (:a("b"))
in block <unit> at <unknown file> line 1
Та же проблема возникает с мешком и набором. Сделайте это с помощью Map , и вы получите изменяемый хэш.
Я полагаю, что здесь есть множество проблем, но, возможно, Сигилла% не так универсальна, как мне казалось.3 ответа:
Вы можете использовать
Вы должны быть осторожны, как вы обнаружили, в том, как вы объявляете и назначаете.%сигилированные контейнеры для хранения любого значения, котороеdoesAssociativeроль.В вашем примере,
my Pair %pair, вы говорите, чтобы сделатьHash(НеPair), который может содержатьPairзначения (%pair.WHAT = 'Hash[Pair]')Попробуйте вот что:
my Pair %p2 = mykey => Pair.new: 'a', 'b';Что может быть приятно. Ограничивая тип значений, вы получите ошибку, если скажете
%p2<c> = 'd';Поскольку вы не назначаете
Привязка, как вы также обнаружили, работает так, как вы считаете нужным.Pair.
Нам нужно сделать несколько шагов назад, если мы хотим понять, что происходит с вашими примерами:
Переменные привязаны к объектам. По умолчанию сигиллированные переменные изначально привязаны к назначаемым объектам контейнера (Scalarдля$и&,Arrayдля@иHashдля%).Если вы добавляете тип к объявлению переменной, например
my Int %varИли эквивалентно
my %var of IntВы устанавливаете ограничение на типы значений, которые может иметь этот контейнер. держать.
Присваивание переменной (
=) пытается поместить значение с правой стороны в контейнер, связанный с переменной с левой стороны, что приведет к ошибке, если это ограничение типа не будет выполнено. По умолчанию только переменные&имеют такое ограничение (cf(my &).VAR.ofvs(my %).VAR.of).Напротив, повторная привязка переменной (
:=) заменит объект контейнера. Если вы хотите установить ограничения на то, какие типы объектов могут быть связаны, вам нужноisвместо этого, еслиof:my %var is Pair; %var := x => 1; # ok %var := 42; # not okСигиллированные переменные подразумевают контраинты типа по умолчанию (нет для
$,Callableибо&,Positionalдля@иAssociativeдля%). Обратите внимание, что это ограничение по умолчанию переопределяется явным, напримерНаконец, обратите внимание, чтоmy %var is Int; %var := 42; # ok even though 42 is not Associativeisне просто устанавливает ограничение типа, но также привязывает переменную к вновь созданному экземпляру этого типа:Я не знаю никакого способа просто сделать первое.my %pair is Pair; say %pair; # (Mu) => (Mu), ie Pair.new()