Метод 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
Другие вопросы по тегам