Метод total и символ переменной Bag в Perl 6
Мы можем использовать total
метод, чтобы узнать сумму всех весов в Bag
,
> my $b = (1,2,1).Bag
Bag(1(2), 2)
> $b.total
3
Но если мы используем %
символ вместо $
за наших Bag
, мы получаем сообщение об ошибке.
> my %b = (1,2,1).Bag
{1 => 2, 2 => 1}
> %b.total
No such method 'total' for invocant of type 'Hash'. Did you mean 'cotan'?
in block <unit> at <unknown file> line 1
Если %b
явно преобразуется в Bag
до total
, оно работает:
> %b.Bag.total
3
Вопрос: раньше я думал, что с Set
, Bag
, SetHash
и т. д., используя %
сигил предпочтительнее. Я ошибся?
2 ответа
Привязать вместо присвоить
my %b := (1,2,1).Bag;
say %b.total
Связывание (с :=
) связывает правую сторону непосредственно с левой стороны. В этом случае значение, которое делает Associative
роль связана с %b
,
Или назначить Bag
Назначение (с =
) присваивает (копирует) значения с правой стороны в контейнер с левой стороны.
Вы можете назначить после первой привязки к Bag
следующее.
Непосредственно перед назначением my
объявитель свяжет подходящий контейнер с объявленной переменной. По умолчанию это будет Hash
контейнер, если переменная имеет %
сигил.
Но вы можете указать переменную is
связан с другим типом контейнера, который совместим с его сигилой:
my %b is Bag = 1,2,1;
say %b.total
С этим заклинанием вам нужно использовать =
потому что к тому времени, когда встречается оператор %b
уже был привязан к Bag
и теперь вам нужно назначить (скопировать) в Bag
,
Таким образом, вы получаете простоту предоставления списка значений (без явных ключей или Bag
Принуждение / конструктор необходим) потому что =
интерпретируется в соответствии с потребностями контейнера слева, и Bag
выбирает интерпретировать RHS =
как список ключей, чье количество встречений имеет значение для него.
В Perl 6 присвоение контейнеру может быть принудительным, то есть оно приводит значение к значению контейнера. Видеть это:
my $b = (1,2,1).Bag;
say $b.^name; # Bag
my %haШ = (1,2,1).Bag;
say %haШ.^name; # Hash
Привязка, с другой стороны, привязывает тип контейнера к содержащейся вещи.
Итак, ответ: вы все еще можете использовать сигилу, но, как сказано выше @raiph, используйте связывание, чтобы Bag или BagHash не приводились к простому хешу.
my %real-haШ := (1,2,1).Bag;
say %real-haШ.^name; # Bag