Может ли 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 ответа:
Вы можете использовать
Вы должны быть осторожны, как вы обнаружили, в том, как вы объявляете и назначаете.%
сигилированные контейнеры для хранения любого значения, котороеdoes
Associative
роль.В вашем примере,
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.of
vs(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 Associative
is
не просто устанавливает ограничение типа, но также привязывает переменную к вновь созданному экземпляру этого типа:Я не знаю никакого способа просто сделать первое.my %pair is Pair; say %pair; # (Mu) => (Mu), ie Pair.new()